Skip to content

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

Merged
MQ37 merged 8 commits intomainfrom
fix/e2e-tsx-race-condition
Mar 3, 2026
Merged

fix: add tsx as devDependency to prevent E2E test race condition#12
MQ37 merged 8 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?

MQ37 added 2 commits March 3, 2026 15:38
commit 1e35f2f
Author: Dušan Vystrčil <vystrcil.dusan@gmail.com>
Date:   Tue Mar 3 10:25:50 2026 +0100

    fix: flush stdout before process.exit() to prevent pipe truncation (#17)

    When mcpc output exceeds 64KB and stdout is piped (e.g. `mcpc ... --json | jq`),
    the output was silently truncated at exactly 65,536 bytes (the kernel pipe buffer
    size), producing broken JSON.

    Root cause: when stdout is a pipe, Node.js uses async I/O. `process.exit(0)`
    terminates the process before buffered data is fully written to the pipe. When
    stdout is a file or TTY, Node.js uses sync I/O, so data is written before exit.

    The fix waits for stdout to drain before calling process.exit(0).

    Reproduction:
      mcpc @apify tools-call get-actor-output datasetId:="..." --json | wc -c

    Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

commit c7ea6f2
Author: Jan Curn <jan.curn@gmail.com>
Date:   Mon Mar 2 13:15:22 2026 +0100

    Updated CHANGELOG.md, improved release process

commit 3861f51
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Mon Mar 2 11:19:49 2026 +0100

    Add renovate.json (#13)

    Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

commit ba193b8
Author: Jan Curn <jan.curn@gmail.com>
Date:   Sun Mar 1 23:36:16 2026 +0100

    v0.1.10

commit 8400ca3
Author: Jan Curn <jan.curn@gmail.com>
Date:   Sun Mar 1 23:21:57 2026 +0100

    Added support for `HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY` env vars (#10)

    * Added support for `HTTPS_PROXY` / `https_proxy` / `HTTP_PROXY` / `http_proxy` env vars

    * Improvements

    * Improvements

    * Fixes

    * Fixes

    * Nits
@MQ37 MQ37 marked this pull request as ready for review March 3, 2026 23:40
@MQ37
Copy link
Collaborator Author

MQ37 commented Mar 3, 2026

some test are still failing in CICD, but let's merge it - it is in better state than it was before. @jancurn

@MQ37 MQ37 merged commit 8fe2aa9 into main Mar 3, 2026
5 checks passed
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.

3 participants