Skip to content

fix(#493): make the proxy-init timeout say what actually stalled - #509

Merged
debugmcpdev merged 1 commit into
mainfrom
fix/493-honest-init-timeout
Aug 27, 2026
Merged

fix(#493): make the proxy-init timeout say what actually stalled#509
debugmcpdev merged 1 commit into
mainfrom
fix/493-honest-init-timeout

Conversation

@debugmcpdev

Copy link
Copy Markdown
Collaborator

Summary

The 30s init-timeout message — "the debug adapter failed to start or is not properly configured; check that it is installed" — was written for the nothing-ever-connected case and is confidently wrong for every other stage. In #492's incident the adapter spawned, connected, and emitted a DAP event; the one diagnostic fact that mattered (which handshake request is outstanding) was known worker-side and discarded. For an agent this is a directed wrong lead: it verifies rdbg --version, finds it healthy, and has nowhere to go.

Changes

  • Worker → parent progress statuses (existing status IPC): adapter_spawned {pid} after spawn, and dap_handshake_stage {stage: transport_connected | request_pending | response_received, command} around each blocking init request (initialize/launch/attach — all four flow variants). Handled imperatively only, deliberately no dap-core case (the adapter_capabilities convention) so nothing is double-processed; the new names deliberately avoid adapter_connected, whose handler unblocks the js-debug queueing handshake.
  • Stage-aware ErrorMessages.proxyInitTimeout(timeout, progress?) keeping the first sentence invariant (pinned by existing tests, quoted in docs):
    • connected + request outstanding → names the request and the live adapter PID: "…the "initialize" request never received a response. The adapter process is running (PID N). This is an adapter-side protocol stall, not a missing install…" (+ a DAP_TRACE pointer)
    • connected, nothing outstanding → "handshake began, but initialization stalled before completing"
    • spawned but never connected → says that (port/loopback hint)
    • no progress → the original install-hint text, the case it correctly describes
    • PID note omitted in connect mode (ruby remote attach has no adapter process)
  • Structured facts reach the agent: the timeout Error carries initProgress; the failed start_debugging result now includes data: { initProgress, proxyLogPath } (previously these were only server-side logs), following the existing MSVC-branch data precedent.
  • Updated the three architecture/pattern docs that quote the excerpt.

Tests

  • Message matrix for every progress shape incl. the invariant prefix (error-messages.test.ts).
  • ProxyManager: statuses replayed → timeout names the request + PID and carries initProgress; answered requests no longer read as pending; the existing no-progress timeout tests pass unchanged (they simulate init_received progress and pin the invariant sentence).
  • Worker: ordered emission sequence pinned (spawned → transport_connected → initialize pending/received → launch pending/received).
  • Full worker/proxy/session unit + core suites green.

Pairs with #507 (#492's recovery): a fully-wedged adapter that also withholds the launch response still times out — and now the message names the launch request instead of blaming the install.

Fixes #493

🤖 Generated with Claude Code

The 30s init-timeout message — "the debug adapter failed to start or is
not properly configured; check that it is installed" — was written for
the nothing-ever-connected case and was confidently wrong for every
other stage. In #492's incident the adapter spawned, opened its socket,
accepted the connection, and emitted a DAP event; the one missing thing
was a response frame, and the one diagnostic fact that names it (which
handshake request is outstanding) was known worker-side and discarded.
For an agent that is worse than unhelpful: it is a directed wrong lead.

The worker now reports init progress over the existing status IPC:
adapter_spawned {pid} and dap_handshake_stage {transport_connected |
request_pending | response_received, command} around each blocking
handshake request (initialize/launch/attach). Both statuses are handled
imperatively only — deliberately no dap-core case, following the
adapter_capabilities convention, so nothing is double-processed and the
js-debug launch barrier is untouched ('adapter_connected' keeps its
unblock semantics; the new status names avoid it on purpose).

ProxyManager tracks the progress and the timeout message now reflects
the reached stage, keeping the first sentence invariant (tests pin it,
docs quote it): connected + request outstanding names the request and
the live adapter PID and says "protocol stall, not a missing install";
spawned-but-never-connected and connected-but-idle get their own
wording; the install hint survives only for no-progress. The structured
facts ride on the Error object and land in the failed start_debugging
result's data ({initProgress, proxyLogPath}) — previously they were
logged server-side where the agent reading the error can't see them.

Fixes #493

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.24561% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/session/session-manager-operations.ts 87.50% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@debugmcpdev
debugmcpdev merged commit 3b68697 into main Aug 27, 2026
10 checks passed
@debugmcpdev
debugmcpdev deleted the fix/493-honest-init-timeout branch August 27, 2026 04:43
debugmcpdev added a commit that referenced this pull request Aug 27, 2026
…#510)

Self-debugging RCA writeup of the #492 Ruby launch stall: the incident
log, why #470's decoder paths were ruled out, mcp-debugger stepping
through its own compiled MinimalDapClient (statement breakpoints in
dist/, evaluate_expression against pendingRequests, the stack of the
event-delivery moment), the fake-rdbg replay with its DAP trace, the
rdbg 1.11.0 source analysis (silent `if sock = @sock` drop guard,
unsynchronized cleanup_reader) with the seq discriminator for the next
live capture, and what #507/#509 changed. Honest about proven vs.
hypothesized.

Also: troubleshooting gains a section decoding the stage-aware 30s
init-timeout message (post-#493), the ruby guide's troubleshooting
table maps the new recovery warning to the case study, and the README
documentation index links it.

Co-authored-by: JF <john.franklin@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

Proxy-init timeout misattributes the cause: says the adapter 'failed to start' when it connected fine and a DAP request simply never got a response

2 participants