fix: catch BrokenPipeError in stdio stdout_writer#3097
Open
Lexus2016 wants to merge 1 commit into
Open
Conversation
When the parent process (MCP client) closes the stdout pipe during restart, kill, or graceful shutdown, stdout_writer() raises BrokenPipeError at 'await stdout.flush()'. The existing handler only catches anyio.ClosedResourceError, so the BrokenPipeError propagates through anyio's TaskGroup as an unhandled ExceptionGroup, crashing the entire MCP server process. This is a common production scenario: any MCP client restart (config reload, session reset, crash recovery) kills the server, requiring manual cleanup of stale daemon locks and process restarts. Fix: extend the except clause to also catch BrokenPipeError and ConnectionResetError, treating them as graceful shutdown signals. Tested in production with Hermes Agent (Nous Research) as the MCP client and turbo-memory-mcp as the server.
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.
Problem
When the parent process (MCP client) closes the stdout pipe — during restart, kill, or graceful shutdown — the
stdout_writer()coroutine instdio_server()raisesBrokenPipeErroratawait stdout.flush()(line 81).The existing handler only catches
anyio.ClosedResourceError, which does not coverBrokenPipeError. The unhandled exception propagates through anyio'sTaskGroupas anExceptionGroup, crashing the entire MCP server process.Reproduction
turbo-memory-mcp serve)kill -9or close stdin)Impact
This is a common production scenario — every MCP client restart (config reload, session reset, crash recovery) kills the server. Downstream servers like
turbo-memory-mcpleave stale daemon locks and require manual cleanup (pkill,rm lockfile, reconnect).Fix
Extend the
exceptclause instdout_writer()to also catchBrokenPipeErrorandConnectionResetError, treating them as graceful shutdown signals:Testing
Tested in production with Hermes Agent (Nous Research) as the MCP client and
turbo-memory-mcpas the server. The fix has been running reliably — server now exits cleanly on client restart instead of crashing withExceptionGroup.