Skip to content

fix: add tsx as devDependency to prevent E2E test race condition#12

Draft
MQ37 wants to merge 6 commits intomainfrom
fix/e2e-tsx-race-condition
Draft

fix: add tsx as devDependency to prevent E2E test race condition#12
MQ37 wants to merge 6 commits intomainfrom
fix/e2e-tsx-race-condition

Conversation

@MQ37
Copy link
Collaborator

@MQ37 MQ37 commented Feb 28, 2026

Summary

  • Adds tsx as a devDependency to fix E2E test failures in CI

Problem

All 16 E2E tests run in parallel and each invokes npx tsx to start the test MCP server. Without tsx installed locally, all 16 processes race to download and install it into ~/.npm/_npx/ simultaneously, causing:

  • ENOTEMPTY errors (directory not empty during npm install)
  • TAR_ENTRY_ERROR (corrupted tar extraction)
  • sh: 1: tsx: not found (install failed silently)

This has been the root cause of all 19 failing E2E tests on CI across PRs.

Fix

Adding tsx to devDependencies ensures it's available locally after npm install. When npx tsx runs, it resolves the local binary instantly with no network download or install step, eliminating the race condition entirely.

MQ37 added 6 commits February 28, 2026 11:21
When 16 E2E tests run in parallel, each invokes 'npx tsx' to start the
test server. Without tsx installed locally, all 16 processes race to
download and install tsx into ~/.npm/_npx/ simultaneously, causing
ENOTEMPTY, TAR_ENTRY_ERROR, and 'tsx: not found' failures.

Adding tsx as a devDependency ensures it's available locally and npx
resolves it instantly without any network/install race.
- bridge-resilience: use --isolated to prevent shared sessions.json
  pollution from parallel tests causing INVARIANT VIOLATION
- header-security: replace hardcoded sleep with wait_for ping polling
  to ensure bridge is ready before assertions
- proxy: replace all hardcoded sleeps with wait_for health endpoint
  polling; use --isolated to avoid session file contention
- server-abort: add wait_for health check after server reset and
  ping polling after connect; use --isolated
The connect command was failing with exit code 1 when showServerDetails()
couldn't reach the bridge fast enough after session creation. The session
was already created successfully — the bridge just needed more time to
complete MCP initialization.

Now showServerDetails is best-effort on connect: if it fails, the session
is still valid and the next command will trigger ensureBridgeReady which
handles retries properly.
The previous commit swallowed all errors from showServerDetails, including
auth errors. This caused 'mcpc <oauth-server> connect @name' to succeed
even when the server requires authentication. Auth errors must propagate
so users get the login hint.
…errors

ensureBridgeReady() now retries up to 3 times (1s apart) when the bridge
socket is temporarily unresponsive, instead of immediately restarting the
bridge. This prevents false-positive restarts caused by transient event
loop stalls (common under CI load).

Also adds wait_for ping readiness polling after connect in 3 E2E tests
(header-security, proxy, server-abort) as defense-in-depth.
The retry logic in ensureBridgeReady() added up to 12s of extra latency
per failed health check, causing cascading lock contention on the shared
sessions.json across 16 parallel E2E tests. Revert to single-shot check;
the wait_for ping additions in the test scripts are sufficient.
@jancurn
Copy link
Member

jancurn commented Mar 1, 2026

Is this good to merge?

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.

2 participants