fix(client): swallow synchronous EPIPE from writeAfterFIN (#3282)#3283
Merged
Conversation
net.Socket.write can throw synchronously with code 'EPIPE' on a half-closed socket, before the 'close' event fires. The throw escaped RedisSocket.write from a setImmediate flush and crashed the process. Preflight `writable`, wrap the cork/write loop in try/finally so uncork always runs, and narrowly swallow EPIPE — the close handler will reject the pending command via #waitingForReply. Fixes redis#3282 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace `any` casts with `unknown` and rename the unused `err` parameter to `_err` so `lint:changed` passes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The write tests in redis#3282 left the underlying TCP connection alive, which made server.close() wait forever and tripped Mocha's 2000ms timeout on CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PavelPashov
approved these changes
May 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
net.Socket.write can throw synchronously with code 'EPIPE' on a half-closed socket, before the 'close' event fires. The throw escaped RedisSocket.write from a setImmediate flush and crashed the process. Preflight
writable, wrap the cork/write loop in try/finally so uncork always runs, and narrowly swallow EPIPE — the close handler will reject the pending command via #waitingForReply.Fixes #3282
Description
Checklist
npm testpass with this change (including linting)?Note
Medium Risk
Medium risk because it changes low-level socket write behavior and error handling; mistakes could hide real network failures or affect backpressure/flush behavior under load.
Overview
Prevents process crashes when
net.Socket.writethrows synchronously on half-closed connections by guardingRedisSocket.writewith awritablecheck, ensuringuncork()always runs viatry/finally, and swallowing onlyEPIPEwhile rethrowing other errors.Adds targeted unit tests that capture the underlying
net.Socketto verify: no writes occur when the socket is not writable, synchronousEPIPEis ignored, and non-EPIPEerrors still surface.Reviewed by Cursor Bugbot for commit 1452cac. Bugbot is set up for automated code reviews on this repo. Configure here.