Skip to content

fix(pi-cursor-agent): prevent uncaughtException on socket reset and handle network reconnections - #33

Open
zhangyang-crazy-one wants to merge 1 commit into
sudosubin:mainfrom
zhangyang-crazy-one:fix/cursor-agent-socket-reset-uncaught-exception
Open

zhangyang-crazy-one wants to merge 1 commit into
sudosubin:mainfrom
zhangyang-crazy-one:fix/cursor-agent-socket-reset-uncaught-exception

Conversation

@zhangyang-crazy-one

Copy link
Copy Markdown

Summary

Fixes #32.

Prevents pi-cursor-agent from crashing the host Pi process with uncaughtException when HTTP/2 socket connections are reset abruptly (ECONNRESET / Client network socket disconnected before secure TLS connection was established). Also enables automatic retry and reconnection on transient connection drops.

Changes

  • Session Guard in AgentService: Installs an error listener guard on http2.ClientHttp2Session ensuring that lingering destruction errors during connection teardown do not escape as uncaughtException after ConnectRPC's Http2SessionManager detaches its listener.
  • Socket Guard in createConnection: Supplies a guarded createConnection hook in nodeOptions to ensure underlying TLS and TCP sockets have permanent error listeners to absorb unhandled reset events during TLS handshake or teardown.
  • Retriable Network Errors in AgentConnectClient: Extends isRetriableError to recognize ECONNRESET, client network socket disconnected, and socket hang up as retriable connection errors, enabling exponential backoff reconnection.
  • Tests: Adds unit tests in test/api/agent-service.test.ts verifying that socket resets are handled cleanly without triggering uncaughtException.

Verification

  • npm run typecheck passed cleanly
  • npm run lint passed without issues
  • npm test passed (36/36 tests passing, including newly added socket reset tests)
  • Verified locally that abrupt socket disconnection rejects properly without bubbling to process.on("uncaughtException").

…andle network reconnections

When network connection to api2.cursor.sh is reset or terminated abruptly
(e.g., ECONNRESET during TLS handshake or keep-alive teardown), ConnectRPC's
Http2SessionManager removes its error listener upon error. The underlying
TLS socket and HTTP/2 session then emit secondary error events during
destruction in microtasks (onConnectEnd/processTicksAndRejections). Because
no listener remains on the EventEmitter, Node/Bun raises an uncaughtException
which terminates the host Pi process.

Changes:
- Add a session-level error guard in AgentService ensuring ClientHttp2Session
  always retains an error listener to swallow lingering destruction errors.
- Pass custom createConnection in nodeOptions to guard underlying TLS and TCP
  sockets from bubbling unhandled reset errors.
- Expand isRetriableError in AgentConnectClient to classify ECONNRESET,
  socket hang up, and client network disconnection as retriable errors.
- Add unit tests verifying socket reset errors are handled gracefully without
  triggering uncaughtException.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[pi-cursor-agent] Process crashes on ECONNRESET / socket disconnection with uncaughtException

1 participant