fix(server): install uncaught error handlers for library consumers#505
Open
Alexander-Ollman wants to merge 1 commit into
Open
fix(server): install uncaught error handlers for library consumers#505Alexander-Ollman wants to merge 1 commit into
Alexander-Ollman wants to merge 1 commit into
Conversation
…r library consumers The CLI (bin/cli.ts) has long installed process-level handlers that log and swallow socket-level errors (EPIPE, ECONNRESET) and SDK subprocess crashes instead of letting them kill the proxy. Until now those handlers lived only in the CLI, so library consumers — e.g. era-code calling startProxyServer in-process — had no safety net: a single mid-stream EPIPE crashed the host process and orphaned downstream agents (which then saw ECONNRESET, then ConnectionRefused, and entered an unbounded retry loop). Lift the safety net into the library entry behind an opt-in flag so existing library consumers' handler choices are preserved by default. Changes - src/proxy/types.ts: add `installProcessErrorHandlers?: boolean` to ProxyConfig - src/proxy/server.ts: export `installProxyProcessErrorHandlers()` (idempotent); startProxyServer calls it when the config flag is true - bin/cli.ts: pass `installProcessErrorHandlers: true` and remove the duplicate handler block — single source of truth - src/__tests__/install-process-error-handlers.test.ts: verifies the helper attaches both listeners and is idempotent on repeat calls
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.
Summary
bin/cli.tshas long installedprocess.on('uncaughtException')andprocess.on('unhandledRejection')handlers that log and swallow socket-level errors (EPIPE, ECONNRESET) and SDK subprocess crashes instead of letting them kill the proxy. Until this PR those handlers lived only in the CLI, so library consumers callingstartProxyServerin-process had no safety net.In our setup (era-code starts meridian via
await import('@rynfar/meridian')andstartProxyServer({...})so it can run inside the same Node process as the OpenCode wrapper) a single mid-stream EPIPE was crashing the host process and orphaning OpenCode, which then sawECONNRESETon the in-flight request, thenConnectionRefusedon retries, and entered an unbounded retry loop withCannot connect to API: Unable to connect…until the user killed it.This PR moves the safety net into the library entry behind an opt-in flag, so any library consumer can enable it (and the bundled CLI already does).
Changes
src/proxy/types.ts— addinstallProcessErrorHandlers?: booleantoProxyConfig. Defaults to false to preserve any handlers a library consumer has already installed.src/proxy/server.ts— exportinstallProxyProcessErrorHandlers()(idempotent).startProxyServercalls it wheninstallProcessErrorHandlers: trueis passed.bin/cli.ts— passesinstallProcessErrorHandlers: trueintostart({...})and removes the now-duplicate handler block. The CLI's behavior is byte-identical to before; the handlers are now installed in exactly one place.src/__tests__/install-process-error-handlers.test.ts— verifies the helper attaches both listeners and is idempotent on repeat calls.Test plan
bun test src/__tests__/install-process-error-handlers.test.ts— 2 passbun build bin/cli.ts src/proxy/server.ts --outdir dist --target node --splitting --external @anthropic-ai/claude-agent-sdk --entry-naming '[name].js'succeeds; bothdist/cli.jsanddist/server.jsparse cleanly withnode --checkinstallProxyProcessErrorHandlerssymbol present in the builtdist/server.jsbundlebun testto confirm no regressions in adjacent suitesCompatibility
[PROXY] Uncaught exception (recovered): …).installProcessErrorHandlers: true(or call the new exported helper). No silent change to global process state.