Repo: motir-core. One PR. The shared sign-in helper reports success too early, so the very next page.goto(...) in a spec is aborted by the tail of the auth redirect. Three occurrences, three different specs, two lanes, all on innocent diffs.
Error: page.goto: Navigation to "http://localhost:3200/items" is interrupted by
another navigation to "http://localhost:3200/dashboard"
235 | await page.context().clearCookies();
236 | await signIn(page, VIEWER_EMAIL, VIEWER_PASSWORD);
> 237 | await page.goto('/items');
_helpers/shell-session.ts's signIn() (and signUp()) end at await page.waitForURL('**/dashboard'). That resolves on the FIRST URL match — but the post-auth router.replace can still have a second client-side navigation to /dashboard in flight, and it aborts the caller's explicit goto.
Two failure shapes, same cause — the duration is not the tell, the phrase interrupted by another navigation inside the call log is:
goto is bare — reads as an instant error;goto sits inside a toPass({timeout: 90_000}) retry wrapper — reads as a 90s hang.| # | date | PR | spec | lane |
|---|---|---|---|---|
| 1 | 2026-07-28 | #1640 | acceptance-augment-replan.spec.ts:196 | acceptance-video |
| 2 | 2026-08-01 | #1772 | collab-at-scale.spec.ts:352 (via warmIssueRoutes) | collab-at-scale |
| 3 | 2026-08-10 | #2025 | acceptance-quick-view-edit.spec.ts:237 | acceptance-video 3/4 |
Occurrence 3's spec landed on 2026-08-07 (MOTIR-2560 / #2017) — i.e. the shape is being copied into new specs faster than it is being worked around, which is the argument for fixing the helper rather than each caller.
Not a product regression. Occurrence 3's proof was structural and took one command: the spec did not exist on the branch at all (ls tests/e2e/acceptance-quick-view-edit.spec.ts → No such file). PR CI checks out the branch merged with main, so a spec that arrived on main after your last merge can red-light your PR while being absent from your tree.
Fix it once, in the helper — not in each caller, and not with a sleep.
signIn() / signUp() must not return until the auth redirect has SETTLED: after waitForURL('**/dashboard'), also await an authoritative dashboard signal (a heading / a data-testid the dashboard owns) so no further navigation is queued.page.goto immediately after signIn must be safe by construction — that is the property under test.signIn() and signUp() return only after the dashboard has settled, and the wait is on an authoritative signal — no waitForTimeout (CLAUDE.md § E2E forbids a sleep as synchronisation).goto another route immediately, assert it lands. Falsifiable, not tautological.MOTIR-2617's rank=popular webServer-degradation mode and MOTIR-1565's sign-up-404 mode. Both are different failures on adjacent surfaces; do not fold them in. In particular this one is not capacity — it reproduces on a healthy server and is a genuine ordering bug in the helper.