# RED.stop is not a function

**URL:** https://discourse.nodered.org/t/red-stop-is-not-a-function/97079
**Category:** General
**Tags:** docker
**Created:** [15 May 2025 11:46 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079 "2025-05-15T11:46:21Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![malee](https://avatars.discourse-cdn.com/v4/letter/m/ac8455/32.png) [@malee](https://discourse.nodered.org/u/malee)
#### Post date: [15 May 2025 11:46 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/1 "2025-05-15T11:46:21Z")

</div>

I am working on a way of gracefully stopping a node-RED instance from running to simply the task of bench marking with clinic.js and auto cannon. To allow for this to happen I initially tried using a call to `RED.stop()` in a function node.

When doing so I received a Type error: RED.stop is not a function.

I then tried installing a simple node that just registers an endpoint, the HTML file is just a script tag:

```auto
module.exports = function(RED) {
         try {
                const shutdownEndpointPath = '/my-secret-shutdown-trigger';
                RED.httpAdmin.get(shutdownEndpointPath, function(req, res) {
                    RED.log.info(`Custom shutdown endpoint (${shutdownEndpointPath}) called. Initiating Node-RED shutdown`);
                    res.status(200).json({message: "Node-RED shutdown sequence initiated"});
                    setTimeout(() => {
                        RED.stop();
                    }, 100);
                });
                RED.log.info(`Custom shutdown endpoint registered. Access it at [Your Node-RED Admin Root URL]${shutdownEndpointPath}`);
            } catch(err) {
                RED.log.error("Failed to register custom shutdown endpoint in settings.js " + err.toString());
            }
}

```

Again same Type error.

I am running v4.0.9 of Node-RED on LInux 22.04 with Node v22.15.0 in a docker container.

---

<div class="post-metadata">

### Author: ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)
#### Post date: [15 May 2025 12:08 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/2 "2025-05-15T12:08:24Z")

</div>

Hi @malee

Nodes don't have access to the runtime lifecycle apis; they can't stop the runtime directly.

You'd need to go down the embedded route ([docs](https://nodered.org/docs/user-guide/runtime/embedding)) as that will give you access to the top level `RED` api and control over the full lifecycle.

---

<div class="post-metadata">

### Author: ![malee](https://avatars.discourse-cdn.com/v4/letter/m/ac8455/32.png) [@malee](https://discourse.nodered.org/u/malee)
#### Post date: [15 May 2025 16:45 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/3 "2025-05-15T16:45:55Z")

</div>

Hi @knolleary,

Managed to get a result using `autocannon` with the clinic Heap Profiler.

It seems that when `autocannon` completes the exit process is graceful enough to allow for the data to be collected and formatted for analysis.

thanks

Matt

---

<div class="post-metadata">

### Author: ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)
#### Post date: [15 May 2025 17:58 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/4 "2025-05-15T17:58:06Z")

</div>

Could you share your setup with the community?

---

<div class="post-metadata">

### Author: ![malee](https://avatars.discourse-cdn.com/v4/letter/m/ac8455/32.png) [@malee](https://discourse.nodered.org/u/malee)
#### Post date: [16 May 2025 09:38 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/5 "2025-05-16T09:38:55Z")

</div>

Sure no problem, this is the WIP

```auto
const http = require("http");
const express = require("express");
const RED = require("node-red");

const app = express();

const server = http.createServer(app);

const settings = {
  httpAdminRoot: "/",
  httpNodeRoot: "/api",
  userDir: "./.node-red-data/",
  flowFile: "flows.json",
  functionGlobalContext: {},
  logging: {
    console: {
      level: "info",
      metrics: false,
      audit: false,
    },
    
  },
};

RED.init(server, settings);

if (settings.httpAdminRoot) {
  app.use(settings.httpAdminRoot, RED.httpAdmin);
}

if (settings.httpNodeRoot) {
  app.use(settings.httpNodeRoot, RED.httpNode);
}

const SHUTDOWN_TIMEOUT_MS = 30000;
let shutdownTimer;

function gracefulShutdown() {
  console.log("Initiating Node-RED shutdown...");
  RED.stop()
    .then(() => {
      console.log("Node-RED runtime stopped.");
      server.close(() => {
        console.log("HTTP server closed.");
        process.exit(0);
      });
    })
    .catch((err) => {
      console.error("Error stopping Node-RED:", err);
      process.exit(1);
    });
}

const controlApp = express();
const controlServer = http.createServer(controlApp);
const CONTROL_PORT = 8099;

controlApp.get("/shutdown-nodered", (req, res) => {
  console.log("Received /shutdown-nodered request.");
  res.send("Shutdown signal received. Node-RED will attempt to stop.");
  if (shutdownTimer) clearTimeout(shutdownTimer);
  gracefulShutdown();
});

controlServer.listen(CONTROL_PORT, () => {
  console.log(`Control server listening on http://localhost:${CONTROL_PORT}`);
  console.log(
    `Call http://localhost:${CONTROL_PORT}/shutdown-nodered to stop Node-RED`
  );
});

RED.start()
  .then(() => {
    const PORT = settings.uiPort || process.env.PORT || 1880;
    server.listen(PORT, () => {
      console.log(
        `Node-RED embedded and running on http://localhost:${PORT}${
          settings.httpAdminRoot || "/"
        }`
      );
      RED.log.info(`Node-RED version ${RED.version()} started`);
    });
  })
  .catch((err) => {
    console.error("Failed to start Node-RED:", err);
    process.exit(1);
  });

process.on("SIGINT", () => {
  console.log("SIGINT received. Shutting down...");
  if (shutdownTimer) clearTimeout(shutdownTimer);
  gracefulShutdown();
});

```

There is no need to use the shutdown server with the clinic Heap Profiler and `autocannon` as it shuts down gracefully itself. I have also just found that if I comment out `process.exit(0)` and shutdown the Heap Profiler with a `SIGINT` via `CTRL+C` after calling the `shutdown-nodered` endpoint thr Heap Profiler compiles data for visualization after being initialized without `autocannon`

---

<div class="post-metadata">

### Author: ![malee](https://avatars.discourse-cdn.com/v4/letter/m/ac8455/32.png) [@malee](https://discourse.nodered.org/u/malee)
#### Post date: [16 May 2025 11:14 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/6 "2025-05-16T11:14:17Z")

</div>

I have made some adjustments to the initial script and it now works 🙂

I found that if you kill the process with the process `PID` after node-RED has been stopped then clinic.JS completes its tasks as gracefully as you would want.

Solution appears to be replacing the `gracefulShutdown` function with this one:

```auto
function gracefulShutdown() {
  console.log("Initiating Node-RED shutdown...");
  RED.stop()
    .then(() => {
      console.log("Node-RED runtime stopped.");
      server.close(() => {
        console.log("HTTP server closed.");
        process.kill(process.pid, 'SIGINT');
      });
    })
    .catch((err) => {
      console.error("Error stopping Node-RED:", err);
      process.exit(1);
    });
}

```

and remove the following:

```auto
process.on("SIGINT", () => {
  console.log("SIGINT received. Shutting down...");
  if (shutdownTimer) clearTimeout(shutdownTimer);
  gracefulShutdown();
});

```

Result!

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/7/87a912b16731867e1dc749cfdd98063c50b1c992.png)

When for example you run

```auto
clinic heapprofiler -- node start-node-red.js

```

and call the following endpoint to end the process.

```auto
curl http://localhost:8099/shutdown-nodered

```

If for example you run `autocannon` then shutdown is automatic

```auto
clinic heapprofiler --autocannon [http://localhost:8080/api/folderlisting -m POST -d 60] -- node start-node-red.js

```

---

<div class="post-metadata">

### Author: ![AllanOricil](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/allanoricil/32/106911_2.png) [@AllanOricil](https://discourse.nodered.org/u/AllanOricil)
#### Post date: [16 May 2025 12:55 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/7 "2025-05-16T12:55:04Z")

</div>

Really interesting.

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [30 May 2025 12:55 UTC](https://discourse.nodered.org/t/red-stop-is-not-a-function/97079/8 "2025-05-30T12:55:19Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
