e2e-debuglisted
Install: claude install-skill bloknayrb/tandem
# E2E Test Debugging
Post-mortem guide for Playwright E2E failures in Tandem. Complements the `/e2e` skill (which covers the happy path).
## Ports (#1492)
E2E runs on **reserved ports** (`scripts/test-ports.ts`): Vite 4573, backend 4728 (ws) / 4729 (MCP). A running Tandem or `dev:server` on 3478/3479 is fine and is not touched. Three distinct early-abort signatures:
- **Playwright's "http://127.0.0.1:4729/health is already used"** — something (usually a stale E2E server) is answering the reserved MCP port; the backend entry is `reuseExistingServer: false`. Recovery: `fuser -k 4728/tcp 4729/tcp 4573/tcp` and rerun.
- **"Refusing to run this Playwright suite against a server it did not start"** — the `scripts/e2e-guard.ts` identity probe (#1483, now defense-in-depth): something answered :4729 that it could not prove is an E2E server.
- **"…serving a client that does NOT target the harness backend"** — the guard's served-client check: the Vite on :4573 was launched without `VITE_TANDEM_*` (e.g. hand-started), so its client is baked to the product ports and would drive the suite into a real Tandem through the UI. Stop that Vite and let Playwright start its own.
Anything holding the reserved pair that *fails* the health check — wedged, non-HTTP, or sitting on the never-probed :4728 — is silently SIGKILLed by the E2E server's own boot (`freePort()`); that self-healing is why the reserved numbers must never collide with ports any doc tells users to occupy.
## Pre-Flight Checkl