ECONNREFUSED - Deployed functions work fine, Functions running locally with netlify-cli are failing

I’m running a function using the hello world example from documentation (Get started with functions | Netlify Docs).

I can log messages, and do other variable manipulation in the function code, but as soon as I return a “new Response(“hello world”)” - the function returns the error: connect ECONNREFUSED 127.0.0.1:XXXXX with a 500 status.

When running the command

netlify dev

I get the following error:

Function hello-world has returned an error: connect ECONNREFUSED 127.0.0.1:XXXX

Netlify Environment is using node 20.x.x
Local Docker container is using node 20.15.0

The function works as expected when deploying to Netlify.

This would likely mean the CLI is being terminated due to some reason, so the server is closed. Check your terminal for more info.

Just stumbled upon this as well after following the “Get started with functions” page. Tried running netlify dev --debug, these are the only relevant files when making an HTTP request for the function:

Request from ::1: GET /api/test-fn/1
winston:create-logger: Define prototype method for "error"
winston:create-logger: Define prototype method for "warn"
winston:create-logger: Define prototype method for "info"
winston:create-logger: Define prototype method for "http"
winston:create-logger: Define prototype method for "verbose"
winston:create-logger: Define prototype method for "debug"
winston:create-logger: Define prototype method for "silly"
winston:create-logger: Define prototype method for "error"
winston:create-logger: Define prototype method for "warn"
winston:create-logger: Define prototype method for "info"
winston:create-logger: Define prototype method for "http"
winston:create-logger: Define prototype method for "verbose"
winston:create-logger: Define prototype method for "debug"
winston:create-logger: Define prototype method for "silly"

◈ Function test_fn has returned an error: connect ECONNREFUSED 127.0.0.1:33887
Error: connect ECONNREFUSED 127.0.0.1:33887
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1574:16)

Response with status 500 in 107 ms.

The command that was used to make the request, along with the output:

$ http http://localhost:8888/api/test-fn/1                                                                                                                                                                         
HTTP/1.1 500 Internal Server Error
connection: close
content-length: 158
date: Wed, 14 Aug 2024 00:48:04 GMT
server: Netlify
x-nf-request-id: 01J575PBGS4E4RHVDB9T2A5ZQP
x-powered-by: Express

Error: connect ECONNREFUSED 127.0.0.1:33887
 Error: connect ECONNREFUSED 127.0.0.1:33887
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1574:16)

That port number above, 33887, is random - changes for every request.

Just noticed that the same netlify dev command initially printed ◈ Functions server is listening on 42755 at startup. So why are the port numbers different? Why is the first number random for every request?

Tried adding functionsPort = 8889 to the [dev] section in netlify.toml. It did change the “Functions server is listening on” port number, but the error remains, still with a random port.

Update: I tried using the deprecated approach to functions (use a .js file, define a named export) and it worked flawlessly. So it seems that the problem is with the v2 functions.

After a very brief look at the code, I suspect that maybe the server that’s used for v2 functions is being shut down prematurely, at least on some platforms. FWIW, I’m on Linux and I tried it with Node v18.14.0 and v20.3.0.

Could you provide a minimal reproduction to test?

Sure. But it’s as bare-bones as it gets: GitHub - p-himik/netlify-fn-test

The example seems to work:

and my terminal output:

npx netlify dev
◈ Netlify Dev ◈
◈ Injecting environment variable values for all scopes
◈ Ignored general context env var: LANG (defined in process)
◈ No app server detected. Using simple static server
◈ Running static server from "f-123558"
◈ Setting up local development server
Cleaned up .netlify/functions-internal.

◈ Static server listening to 3999

   ┌─────────────────────────────────────────────────┐
   │                                                 │
   │   ◈ Server now ready on http://localhost:9999   │
   │                                                 │
   └─────────────────────────────────────────────────┘

◈ Loaded function test_fn
Request from ::1: GET /.netlify/functions/test_fn
Response with status 200 in 265 ms.

Did you try a different device?

Just so we’re all on the same page, why not run in a docker container in a minimal image to avoid the “Works on my machine” back-and-forth.

Here’s a docker file I can reliably reproduce the error on:

FROM node:20-bullseye
RUN apt update && apt upgrade -y 
RUN apt install sudo -y
RUN npm install netlify-cli -g

The issue reported here doesn’t seem to be related to the one that happens in that Dockerfile. At least in my case, the logs are:

4.362 Run command for local development
4.362 ────────────────────────────────────────────────────────────────
4.362 ​
4.383
4.383 ◈ Static server listening to 3999
4.386 ​
4.387 (dev.command completed in 23ms)
4.387 Build step duration: dev.command completed in 23ms
4.403 ◈ Functions server is listening on 46687
4.412 ---------------------------
4.412 Error: Unable to open browser automatically: Running inside a docker container
4.412 Please open your browser and open the URL below:
4.412 http://localhost:8888
4.412 ---------------------------
4.420
4.420    ┌─────────────────────────────────────────────────┐
4.420    │                                                 │
4.420    │   ◈ Server now ready on http://localhost:8888   │
4.420    │                                                 │
4.420    └─────────────────────────────────────────────────┘
4.420
4.438 getBinaryVersion failed Error: Command failed with ENOENT: deno --version
4.438 spawn deno ENOENT
4.438     at ChildProcess._handle.onexit (node:internal/child_process:286:19)
4.438     at onErrorNT (node:internal/child_process:484:16)
4.438     at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
4.438   errno: -2,
4.438   code: 'ENOENT',
4.438   syscall: 'spawn deno',
4.438   path: 'deno',
4.438   spawnargs: [ '--version' ],
4.438   originalMessage: 'spawn deno ENOENT',
4.438   shortMessage: 'Command failed with ENOENT: deno --version\nspawn deno ENOENT',
4.438   command: 'deno --version',
4.438   escapedCommand: 'deno --version',
4.438   exitCode: undefined,
4.438   signal: undefined,
4.438   signalDescription: undefined,
4.438   stdout: '',
4.438   stderr: '',
4.438   failed: true,
4.438   timedOut: false,
4.438   isCanceled: false,
4.438   killed: false
4.438 }
4.440 No globalVersion or semver not satisfied. globalVersion: undefined, versionRange: 1.37.0 - 1.44.4
4.443 Error getting cached binary Error: ENOENT: no such file or directory, open '/root/.config/netlify/deno-cli/version.txt'
4.443     at async open (node:internal/fs/promises:639:25)
4.443     at async Object.readFile (node:internal/fs/promises:1242:14)
4.443     at async DenoBridge.getCachedBinary (file:///usr/local/lib/node_modules/netlify-cli/node_modules/@netlify/edge-bundler/dist/node/bridge.js:67:29)
4.443     at async DenoBridge.getBinaryPath (file:///usr/local/lib/node_modules/netlify-cli/node_modules/@netlify/edge-bundler/dist/node/bridge.js:129:28)
4.443     at async Module.serve (file:///usr/local/lib/node_modules/netlify-cli/node_modules/@netlify/edge-bundler/dist/node/server/server.js:197:5)
4.443     at async prepareServer (file:///usr/local/lib/node_modules/netlify-cli/dist/lib/edge-functions/proxy.js:120:28) {
4.443   errno: -2,
4.443   code: 'ENOENT',
4.443   syscall: 'open',
4.443   path: '/root/.config/netlify/deno-cli/version.txt'
4.443 }
4.447 - Setting up the Edge Functions environment. This may take a couple of minutes.
4.448 Downloading Deno CLI to /root/.config/netlify/deno-cli
16.51 ✔ Setting up the Edge Functions environment. This may take a couple of minutes.
16.87 Local version of types is outdated, updating: undefined
16.89 getBinaryVersion failed Error: Command failed with ENOENT: deno --version
16.89 spawn deno ENOENT
16.89     at ChildProcess._handle.onexit (node:internal/child_process:286:19)
16.89     at onErrorNT (node:internal/child_process:484:16)
16.89     at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
16.89   errno: -2,
16.89   code: 'ENOENT',
16.89   syscall: 'spawn deno',
16.89   path: 'deno',
16.89   spawnargs: [ '--version' ],
16.89   originalMessage: 'spawn deno ENOENT',
16.89   shortMessage: 'Command failed with ENOENT: deno --version\nspawn deno ENOENT',
16.89   command: 'deno --version',
16.89   escapedCommand: 'deno --version',
16.89   exitCode: undefined,
16.89   signal: undefined,
16.89   signalDescription: undefined,
16.89   stdout: '',
16.89   stderr: '',
16.89   failed: true,
16.89   timedOut: false,
16.89   isCanceled: false,
16.89   killed: false
16.89 }
16.89 No globalVersion or semver not satisfied. globalVersion: undefined, versionRange: 1.37.0 - 1.44.4
16.89 Using cached Deno CLI from /root/.config/netlify/deno-cli/deno
21.63
21.64  ›   Warning: Error: Netlify CLI has terminated unexpectedly
21.64  ›   This is a problem with the Netlify CLI, not with your application.
21.64  ›   If you recently updated the CLI, consider reverting to an older version by running:
21.64  ›
21.64  ›   npm install -g netlify-cli@VERSION
21.64  ›
21.64  ›   You can use any version from https://ntl.fyi/cli-versions.
21.64  ›
21.64  ›   Please report this problem at https://ntl.fyi/cli-error including the error details below.
21.64  ›
21.64  ›       at error (file:///usr/local/lib/node_modules/netlify-cli/dist/utils/command-helpers.js:168:19)
21.64  ›       at process.<anonymous> (file:///usr/local/lib/node_modules/netlify-cli/dist/commands/main.js:40:5)
21.64  ›       at process.emit (node:events:531:35)
21.64  ›       at process._fatalException (node:internal/process/execution:188:25)
21.64  ›       at throwUnhandledRejectionsMode (node:internal/process/promises:391:5)
21.64  ›       at processPromiseRejections (node:internal/process/promises:470:17)
21.64  ›       at process.processTicksAndRejections (node:internal/process/task_queues:96:32)
21.86
21.86  ›   Warning: Error: Netlify CLI has terminated unexpectedly
21.86  ›   This is a problem with the Netlify CLI, not with your application.
21.86  ›   If you recently updated the CLI, consider reverting to an older version by running:
21.86  ›
21.86  ›   npm install -g netlify-cli@VERSION
21.86  ›
21.86  ›   You can use any version from https://ntl.fyi/cli-versions.
21.86  ›
21.86  ›   Please report this problem at https://ntl.fyi/cli-error including the error details below.
21.86  ›
21.86  ›       at error (file:///usr/local/lib/node_modules/netlify-cli/dist/utils/command-helpers.js:168:19)
21.86  ›       at process.<anonymous> (file:///usr/local/lib/node_modules/netlify-cli/dist/commands/main.js:40:5)
21.86  ›       at process.emit (node:events:531:35)
21.86  ›       at process._fatalException (node:internal/process/execution:188:25)
21.86  ›       at throwUnhandledRejectionsMode (node:internal/process/promises:391:5)
21.86  ›       at processPromiseRejections (node:internal/process/promises:470:17)
21.86  ›       at process.processTicksAndRejections (node:internal/process/task_queues:96:32)
22.90
22.90  ›   Warning: Error: Netlify CLI has terminated unexpectedly
22.90  ›   This is a problem with the Netlify CLI, not with your application.
22.90  ›   If you recently updated the CLI, consider reverting to an older version by running:
22.90  ›
22.90  ›   npm install -g netlify-cli@VERSION
22.90  ›
22.90  ›   You can use any version from https://ntl.fyi/cli-versions.
22.90  ›
22.90  ›   Please report this problem at https://ntl.fyi/cli-error including the error details below.
22.90  ›
22.90  ›       at error (file:///usr/local/lib/node_modules/netlify-cli/dist/utils/command-helpers.js:168:19)
22.90  ›       at process.<anonymous> (file:///usr/local/lib/node_modules/netlify-cli/dist/commands/main.js:40:5)
22.90  ›       at process.emit (node:events:531:35)
22.90  ›       at process._fatalException (node:internal/process/execution:188:25)
22.90  ›       at throwUnhandledRejectionsMode (node:internal/process/promises:391:5)
22.90  ›       at processPromiseRejections (node:internal/process/promises:470:17)
22.90  ›       at process.processTicksAndRejections (node:internal/process/task_queues:96:32)
23.51
23.51  ›   Warning: Error: Netlify CLI has terminated unexpectedly
23.51  ›   This is a problem with the Netlify CLI, not with your application.
23.51  ›   If you recently updated the CLI, consider reverting to an older version by running:
23.51  ›
23.51  ›   npm install -g netlify-cli@VERSION
23.51  ›
23.51  ›   You can use any version from https://ntl.fyi/cli-versions.
23.51  ›
23.51  ›   Please report this problem at https://ntl.fyi/cli-error including the error details below.
23.51  ›
23.51  ›       at error (file:///usr/local/lib/node_modules/netlify-cli/dist/utils/command-helpers.js:168:19)
23.51  ›       at process.<anonymous> (file:///usr/local/lib/node_modules/netlify-cli/dist/commands/main.js:40:5)
23.51  ›       at process.emit (node:events:531:35)
23.51  ›       at process._fatalException (node:internal/process/execution:188:25)
23.51  ›       at throwUnhandledRejectionsMode (node:internal/process/promises:391:5)
23.51  ›       at processPromiseRejections (node:internal/process/promises:470:17)
23.51  ›       at process.processTicksAndRejections (node:internal/process/task_queues:96:32)
23.80 Error: EPERM: operation not permitted, stat '/proc/1/map_files/55b5cf0e0000-55b5cf0e4000'
23.80
23.80   System:
23.80     OS: Linux 5.15 Debian GNU/Linux 11 (bullseye) 11 (bullseye)
23.80     CPU: (16) x64 13th Gen Intel(R) Core(TM) i5-13500H
23.80   Binaries:
23.80     Node: 20.17.0 - /usr/local/bin/node
23.80     Yarn: 1.22.22 - /usr/local/bin/yarn
23.80     npm: 10.8.2 - /usr/local/bin/npm
23.80   npmGlobalPackages:
23.80     netlify-cli: 17.34.2
23.80
------

This indicates an issue with setting up Deno CLI and it crashes as soon as the CLI starts. However, in the above case the CLI crashes only when visiting the Function’s URL.

In your docker machine you can probably run the following to get Deno installed.

You need curl installed first… so here is the install for curl and deno.

apt install curl -y
curl -fsSL https://deno.land/install.sh | sh

NOTE: it would probably be cool if Netlify had a suggested minimal dockerfile for testing functions. It seems like netlify cli makes some assumptions about what is installed on a dev machine.