Skip to content

test(agent-core-v2): deflake the stdio early-close replay test - #2990

Open
sailist wants to merge 1 commit into
MoonshotAI:mainfrom
sailist:bug-033-08-16-mcp-stdio-early-close-flake
Open

test(agent-core-v2): deflake the stdio early-close replay test#2990
sailist wants to merge 1 commit into
MoonshotAI:mainfrom
sailist:bug-033-08-16-mcp-stdio-early-close-flake

Conversation

@sailist

@sailist sailist commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

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 registration flaked in CI at the assertion that a late-registered onUnexpectedClose listener synchronously replays the buffered close reason.

The test waits for the child process exit to be fully processed by polling callTool until 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 EPIPE and 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:

  • The drain loop now breaks only when the probe fails with 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 as EPIPE keep polling until the existing deadline.
  • The predicate is factored into a small isTransportSettledError helper.

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

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 02edbde

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Aug 17, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@02edbde
npx https://pkg.pr.new/@moonshot-ai/kimi-code@02edbde

commit: 02edbde

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +48 to +50
function isTransportSettledError(error: unknown): boolean {
return error instanceof Error && error.message.includes('Not connected');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

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.

1 participant