Skip to content

Keep the server alive when a response write hits a dead socket#4470

Open
yashranaway wants to merge 1 commit into
pingdotgg:mainfrom
yashranaway:handle-response-write-epipe
Open

Keep the server alive when a response write hits a dead socket#4470
yashranaway wants to merge 1 commit into
pingdotgg:mainfrom
yashranaway:handle-response-write-epipe

Conversation

@yashranaway

@yashranaway yashranaway commented Jul 24, 2026

Copy link
Copy Markdown

What Changed

The Node HTTP server is created through a small guard that attaches an "error" listener to every server response and every upgrade socket. The listener only observes the failure; a new test reproduces the incident shape and proves the process survives and keeps serving.

Why

A client that disconnects while an error response is being written crashes the whole server with an unhandled EPIPE, disconnecting every other client and abandoning in-flight provider work.

Upgrade sockets are the worst case and match the reported incident: once a connection upgrades for websocket RPC, Node's http server detaches its own socket error handling, so an auth rejection written to a vanished client emits an "error" event with no listener anywhere, which escalates to an uncaught exception and terminates the process. Plain response streams have no default error listener either.

The failed request needs no recovery logic: its fiber is already interrupted through the response "close" event. The write failure only needs a listener so it stays contained to the request that died.

Fixes #4410

Testing

  • vp test run apps/server/src/httpResponseErrorGuard.test.ts passes (2/2): an EPIPE on an upgrade socket is contained and the server still answers a follow-up request; normal traffic is untouched and every response carries an error listener
  • vp test run apps/server/src/server.test.ts passes (112/112)
  • pnpm typecheck in apps/server clean
  • vp lint on changed files clean

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Touches core Node HTTP server bootstrap; behavior is limited to swallowing/containing socket write errors without changing request handling logic.

Overview
Prevents the Node HTTP server from exiting when a client disconnects mid-write (e.g. EPIPE on websocket upgrade / auth rejection paths).

Adds guardHttpResponseWriteErrors, which attaches error listeners on every response and upgrade socket so unhandled write failures are observed instead of becoming process-fatal uncaught exceptions. The main server now wraps NodeHttp.createServer() with this guard (Bun path unchanged). New tests assert an upgrade-socket EPIPE is contained and normal requests still succeed.

Reviewed by Cursor Bugbot for commit 5970c0f. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Prevent uncaught exceptions when writing to dead sockets in the Node HTTP server

Introduces guardHttpResponseWriteErrors in httpResponseErrorGuard.ts, which attaches error listeners to HTTP response objects and upgrade sockets, routing write errors (e.g. EPIPE) to an optional callback instead of letting them propagate as uncaught exceptions.

  • The Node branch of HttpServerLive in server.ts wraps NodeHttp.createServer() with this guard so all response and upgrade socket errors are captured automatically.
  • Behavioral Change: write errors on dead sockets that previously crashed the process are now silently swallowed unless a callback is provided.

Macroscope summarized 5970c0f.

A client that disconnects while an error response is being written
crashes the whole Node server with an unhandled EPIPE, disconnecting
every other client and abandoning in-flight provider work. Upgrade
sockets are the worst case: once a connection upgrades for websocket
RPC, Node's http server detaches its own socket error handling, so an
auth rejection written to a vanished client emits an error event with no
listener at all.

Arm every response and upgrade socket with an error listener when the
Node server is created. The failed request is already interrupted
through its close event, so the write failure only needs to be observed
instead of taking down the process.

Fixes pingdotgg#4410
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1b8a471c-ef3f-4352-99bb-56e6a9a0f946

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Jul 24, 2026
@macroscopeapp

macroscopeapp Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved

Defensive bug fix that adds error listeners to prevent uncaught socket write errors from crashing the server process. The change is minimal, well-tested, and doesn't alter business logic - just catches errors that would otherwise terminate the server.

You can customize Macroscope's approvability policy. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Node server crashes with unhandled EPIPE when a client disconnects during an auth error response

1 participant