Skip to content

fix: EADDRINUSE: address already in use - when a stale SOCKET_PATH file already exists - #15449

Merged
teemingc merged 11 commits into
sveltejs:mainfrom
marko-rbn:remove-sock-file
Jun 23, 2026
Merged

fix: EADDRINUSE: address already in use - when a stale SOCKET_PATH file already exists#15449
teemingc merged 11 commits into
sveltejs:mainfrom
marko-rbn:remove-sock-file

Conversation

@marko-rbn

Copy link
Copy Markdown
Contributor

Occasionally socket file is not removed when server crashes/shutdown. This patch attempts to delete the file before restarting the server. Applies similar solution as was pulled into adapter-deno package recently:

https://github.com/NextLegacy/sveltekit-adapter-deno
NextLegacy/sveltekit-adapter-deno#1
NextLegacy/sveltekit-adapter-deno#2

To reproduce, create a sock file, and attempt to start the server:

> node -r dotenv/config index.js
node:events:486
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRINUSE: address already in use /var/home/.../app/.run/stage.sock
    at Server.setupListenHandle [as _listen2] (node:net:1994:21)
    at listenInCluster (node:net:2073:12)
    at Server.listen (node:net:2195:5)
    at Polka.listen (file:///var/home/.../app/stage/index.js:206:22)
    at file:///var/home/.../app/stage/index.js:310:9
Emitted 'error' event on Server instance at:
    at emitErrorNT (node:net:2052:8)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
  code: 'EADDRINUSE',
  errno: -48,
  syscall: 'listen',
  address: '/var/home/.../app/.run/stage.sock',
  port: -1
}

After adding this patch, starting the server succeeds:

> node -r dotenv/config index.js
Listening on /var/home/.../app/.run/stage.sock

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • [*] This message body should clearly illustrate what problems it solves.
  • [*] Ideally, include a test that fails without this PR but passes with it.

Tests

  • [*] Run the tests with pnpm test and lint the project with pnpm lint and pnpm check

Changesets

  • If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running pnpm changeset and following the prompts. Changesets that add features should be minor and those that fix bugs should be patch. Please prefix changeset messages with feat:, fix:, or chore:.

Edits

  • [*] Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.

@changeset-bot

changeset-bot Bot commented Feb 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f1cce34

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@sveltejs/adapter-node Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@Conduitry Conduitry left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels dangerous. If someone accidentally passes the wrong path in the environment variable, we'd be deleting some random file on their system. I'd prefer it to be the caller's responsibility to make sure that the spot for the socket is clear, the way this works in a number of other tools.

If we do decide we want to do this, I'd be in favor of using rm(path, { force: true }) rather than catching and suppressing one specific error.

@yds

yds commented Feb 27, 2026

Copy link
Copy Markdown

This feels dangerous. If someone accidentally passes the wrong path in the environment variable, we'd be deleting some random file on their system.

yes, it "feels" dangerous. however this is the only way to ensure the node server starts up if there's already an existing file of any sort at the same path as SOCKET_PATH

I'd prefer it to be the caller's responsibility to make sure that the spot for the socket is clear, the way this works in a number of other tools.

clearing the SOCKET_PATH before node startup does not fix the edge case where node is running under a supervisor such as BSD daemon(8) and node shuts down or crashes and gets restarted by the supervisor. in that case node goes into a loop unable to start up cuz there's a stale socket file it never cleared because it crashed.

as for "other tools", servers such as OpenLDAP's slapd do always leave a stale socket file laying around and upon startup, slapd always deletes whatever it finds at that path to make room for the socket file it needs to create to be able to start up. which also "feels" dangerous, exactly as you mentioned, but I'd argue it's the caller's responsibility to not shoot oneself in the foot, so to speak. ;)

there's plenty of prior art where servers deal with this issue in different ways. however this is a real world issue where node.js has not yet applied the same fix that was fixed in deno v2.6.7:
fix(ext/net): remove socket file when dropping unix listener (denoland/deno#31947)

but even that fix does not address the edge case where a stale socket file gets left behind cuz node crashes and never gets a chance to clean up the socket file -- running under a supervisor the node proc will go into a loop unable to fully start up cuz there's a stale socket file in the way.

most of the arguments about this have already been hashed out in the denoland thread

If we do decide we want to do this, I'd be in favor of using rm(path, { force: true }) rather than catching and suppressing one specific error.

agreed -- that does look better.

P.S. I'm the one who submitted a similar fix to the NextLegacy/sveltekit-adapter-deno -- I'll make another PR there to do rm(path, { force: true }) as you suggest.

@teemingc teemingc changed the title EADDRINUSE: address already in use - when a stale SOCKET_PATH file already exists fix: EADDRINUSE: address already in use - when a stale SOCKET_PATH file already exists Feb 28, 2026
@teemingc teemingc added the needs-decision Not sure if we want to do this yet, also design work needed label May 6, 2026
@Conduitry

Copy link
Copy Markdown
Member

If something genuinely is a socket file from a previous run, it will have size zero now, correct? What do folks think about statting the file and, if it exists and is zero bytes, automatically deleting it? I think/hope that would be just as usable and low-friction as the current unconditional removal - and it reduces my concerns about deleting the wrong file considerably, as it will just be something with zero bytes.

@Rich-Harris

Copy link
Copy Markdown
Member

implemented that change

Comment thread packages/adapter-node/src/index.js Outdated

@Conduitry Conduitry left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@teemingc teemingc added needs-platform-tests This PR needs to run platform tests in order to merge. and removed needs-decision Not sure if we want to do this yet, also design work needed labels Jun 23, 2026
@teemingc
teemingc merged commit c6c0d6b into sveltejs:main Jun 23, 2026
41 of 43 checks passed
This was referenced Jun 23, 2026
Rich-Harris pushed a commit that referenced this pull request Jun 24, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @sveltejs/kit@2.68.0

### Minor Changes


- feat: expose `RemoteFormEnhanceInstance` and
`RemoteFormEnhanceCallback` types
([#15816](#15816))


- feat: set value of `submit` fields when form is submitted
([#15979](#15979))


### Patch Changes


- fix: skip `native_navigation` when `__data.json` returns 404 on a
static fallback page
([#16135](#16135))


- fix: ignore third-party monkeypatches in `pushState`/`replaceState`
warning detection ([#15267](#15267))


- fix: snapshot form fields on read
([#16150](#16150))


- fix: strip field prefix before erroring on duplicates
([#16151](#16151))


- fix: call reset function via prototype
([#16138](#16138))


- chore: fix navigation `type` hover info
([#16147](#16147))
## @sveltejs/adapter-node@5.5.7

### Patch Changes


- fix: add `X-Accel-Buffering: no` header to `text/event-stream`
responses to prevent reverse proxies such as nginx from buffering
streamed responses
([#16156](#16156))


- fix: delete existing socket file on startup
([#15449](#15449))

- Updated dependencies
[[`c426c6e`](c426c6e),
[`81f253e`](81f253e),
[`8d3c865`](8d3c865),
[`6bde3b6`](6bde3b6),
[`9161740`](9161740),
[`2184960`](2184960),
[`5e319b6`](5e319b6),
[`e82a0a8`](e82a0a8)]:
  - @sveltejs/kit@2.68.0

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
tsushanth added a commit to tsushanth/kit that referenced this pull request Jul 16, 2026
Replace the size===0 heuristic (which can't distinguish stale from live)
with a net.connect() probe. Only remove the socket file when the probe
gets ECONNREFUSED; any other outcome (success, timeout, other error) is
treated as 'live' so we never destroy an active server's socket.

Re-stat and compare inode/dev between probe and rm to close the TOCTOU
window in concurrent cold-start scenarios.

Removes the cluster.isWorker guard added in 9fd278c, which was
correct for Node-native cluster mode but left stale-socket cleanup
broken for all PM2 cluster deployments (every process has
cluster.isWorker===true there).

Fixes sveltejs#15449 sveltejs#16230
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-platform-tests This PR needs to run platform tests in order to merge. pkg:adapter-node

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants