test(agent-core-v2): deflake the stdio early-close replay test - #2990
test(agent-core-v2): deflake the stdio early-close replay test#2990sailist wants to merge 1 commit into
Conversation
|
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 02edbde89d
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| function isTransportSettledError(error: unknown): boolean { | ||
| return error instanceof Error && error.message.includes('Not connected'); | ||
| } |
There was a problem hiding this comment.
Synchronize on close instead of matching SDK text
When @modelcontextprotocol/sdk changes or wraps its uncontracted “Not connected” message, the transport can be fully closed and the replay behavior can remain correct, but this predicate will reject every error until the deadline and fail the test. This replaces the scheduling flake with a dependency-implementation-string failure; synchronize through a controlled process/transport close signal instead of parsing the SDK's error text.
Useful? React with 👍 / 👎.
Related Issue
No linked issue — this fixes a flaky test failure observed in CI (see Problem).
Problem
StdioMcpClient > buffers an early close and replays it on listener registrationflaked in CI at the assertion that a late-registeredonUnexpectedCloselistener synchronously replays the buffered close reason.The test waits for the child process exit to be fully processed by polling
callTooluntil a request fails, then registers the listener. But a failed probe has two possible causes:Not connected: the SDK has fully processed the close (its_onclose()ran, which synchronously buffers the close reason in the client) and now rejects new requests up front.write EPIPE: the child's stdin is gone, but the exit event is still queued in the event loop, so the close reason has not been buffered yet.The loop broke on any error, so under CI scheduling it could stop on
EPIPEand register the listener before the reason was buffered, failing the synchronous-replay assertion. Locally the exit event almost always lands before the probe, which made the flake CI-only.What changed
Test-only fix in
packages/agent-core-v2/test/mcpCore/client-stdio.test.ts:Not connected— a state the SDK reaches only after the close has been fully processed, so the buffered reason is guaranteed to exist at registration time. Early errors such asEPIPEkeep polling until the existing deadline.isTransportSettledErrorhelper.No product behavior changed. Verified: the fixed test ran 40 times under full CPU load with 0 failures, and the full
test/mcpCore/suite passes.Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.