ui-react: attribute unexpected browser closure during parallel-session reload

Open
#2,309 9 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
25/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
playwright, typescript
Domain
testing-qa

Research direction

Read packages/ui-react/tests/parallel-sessions-runtime.test.ts around the launch, teardown, device setup and failing reload at line 816. Re-run the recorded check:pr command from the isolated checkout with DEBUG=pw:browser, capturing owned-process PID, exit or signal, disconnect and cleanup chronology. Done means evidence identifies the browser loss or clearly records the remaining gap and next capture action, while preserving all 46 cases and assertions.

Written by the indexing model from the issue text.

Description

area: ui-react needs: repro priority: p2 type: fix

Out of scope

Do not weaken recovery, approval, draft, tracking or staged-file assertions; raise deadlines; skip runtimes; change default browser/worker concurrency; retry a failure into a green claim; or select a production correction without evidence. This is separate from #2202's pre-send readiness timeout, #2280's steering-Undo timeout and the delivered #1993 response-binding repair.

Context

While qualifying #2288 for #2202, the normal guarded local preflight at head 02b320432bbced92add9964b237ef3cdd5275d05, base dcc09e9c8601f6513eec907cfbf7d3ffbc01bf16, encountered a closed-target error during a 1440px reload, followed by shared-browser-closed failures. The first failure is not a timeout:

mounted parallel sessions > 1440 desktop, light, fine pointer, reduced motion: an approval, all four question forms and running work fold into a summary; a reconnect, a reload and a host restart keep them, and none reads done

The body reaches await a.page.reload() at (await a.page.reload, packages/ui-react/tests/parallel-sessions-runtime.test.ts:816) after aborting recovery-route reads, then throws reload: Target page, context or browser has been closed. Playwright records navigation to the fixture origin while waiting for load. Body time: 15,787.90 ms. The next 17 cases fail immediately at browser.newContext, so this is one initiating closed-target failure followed by cascades, not 18 independently established defects. The first API error alone does not establish when or why the shared browser became unavailable.

The file reports 28 pass / 18 fail, 1,169 assertions, 46 cases, 412.06 s. Required preflight exits 1. Strict types and preceding lint/metadata/fast checks pass. The historical #2202 1279px Subagent Deny case passes before the browser loss. No retry of this failed preflight has been performed.

At this exact source, the browser launches at (browser = await chromium.launch, packages/ui-react/tests/parallel-sessions-runtime.test.ts:241), explicit file teardown closes it at (await browser?.close, same file:247), and device creation owns each context at (async function device, same file:357-428). The initiating failure has no retained browser PID, child exit code/signal, pw:browser lifecycle log or close-call ownership trace.

Conditions and observed limits

Bun 1.4.3, Playwright 1.63.0, real Chromium 152.0.7977.82, frozen dependencies, mandatory package/client build, BRAIN_REQUIRE_CHROME=1, the original test preload and local-origin browser guard. This is the ordinary serial check:pr import-feedback phase, not a hosted N=2 comparison. Another diagnostic Bun run was active in a separate dedicated checkout and capability-cleared network namespace; shared-host load is uncontrolled and is not a selected cause.

No Chromium coredump was recorded in the 10:20–10:25 UTC window on 2026-10-17. Kernel and systemd-oomd logs in that window supply no OOM-kill, segfault or process-termination attribution. A later memory snapshot is not proof of memory conditions at exit. These negative observations do not rule out every crash, signal or resource limit.

Earlier logger versions passed complete 46-case native matrices at their own source/base identities; the concurrent frozen historical run also passes its matrix. Neither is a matched-source causal control for this occurrence. The latest logger adds passive profile/admission snapshots, but no action, wait or assertion changes; whether source, runtime or an external termination is responsible remains unestablished.

Scope

Capture the browser/process lifecycle at the initiating reload and establish why the browser is gone before choosing a correction. Found during #2202; supports #736's deterministic host-isolated verification outcome and #2121's qualification obligation. #736 already has 100 direct native children at this readback, so this remains standalone by reference; no existing child was moved.

Acceptance criteria

  • Preserve the first failure, all 17 cascades, exact source/runtime/command and limits; do not conflate it with the historical unavailable-Send failure.
  • Capture launch PID, exit code/signal, disconnect and explicit close/cleanup chronology with owned-process evidence. A DEBUG=pw:browser observation-only arm is an appropriate starting point.
  • If it recurs, distinguish intentional cleanup, protocol disconnect, native termination and resource enforcement using direct evidence. Record non-reproducing controls without calling them fixes.
  • Establish a source-bound correction or document the remaining evidence gap and exact next capture action. Any ownership correction must prove an unrelated process/control survives cleanup.
  • Preserve all 46 matrix cases, original deadlines, native input, offline guards and behavioral/negative assertions. Any correction gets an intended failing-first or mutation/restoration receipt, current local preflight and complete selected hosted proof.

Verification

From an isolated checkout at the recorded source with its own frozen dependencies:

BRAIN_REQUIRE_CHROME=1 PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium bun run check:pr --base origin/main

The original import-feedback merge base is dcc09e9c8601f6513eec907cfbf7d3ffbc01bf16. The affected feedback selects packages/ui-react/tests/parallel-sessions-runtime.test.ts. For the next diagnostic arm, retain the same source/actions and add DEBUG=pw:browser to capture process lifecycle. Keep source and actual tested base/head identities separate if main advances. Do not widen waits or suppress browser-close failures.

Contract impact

None selected. This is an internal native-test/process-lifetime investigation, not an established product or protocol regression. Needs reproduction with exit/ownership evidence before an implementation is agent-ready.

Triage 2026-10-17: p2 reflects wanted unscheduled diagnosis, without inheriting the candidate's urgency. Retain needs: repro: the initiating browser exit/close-owner evidence is missing and the 17 later closed-context failures are cascades, not independent causes. Preserve the existing original-source capture recipe and all failed identities. Standalone supporting work for #736, whose native child list is full; discovery during #2202 does not make this browser-lifecycle diagnosis part of its composer deliverable.

Current diagnostic distinction — triage 2026-10-21

The later controlled page-only closure reproduces the first reload error while the same browser still opens an independent context and evaluates a sentinel. It does not reproduce the subsequent 17 newContext failures. Therefore preserve the distinction between the initiating closed-target API error and independently established browser-wide termination; neither actor nor exact close/exit chronology is known for the original run.

The native lifecycle, GPU/shared-memory, crash-observation, raster-concurrency and NetLog controls in the comments did not capture the original browser-wide failure. Their passing 104-assertion scenario results remain separately attributed. The earlier six-session cancellation in a crash-observation arm occurred before reload and is tracked in #2395/#2394; valid-capacity controls reach reload successfully but do not diagnose the historical browser loss. #2471’s later post-Send initial-card timeout also does not establish a common initiating mechanism.

The required next evidence remains a naturally failing original-boundary trace joining actual browser PID/start/exit, page/context state and explicit close/cleanup ownership before the cascades. Preserve the original failure/order and all guards; no source correction, new browser execution, causal fix, priority, parent or readiness change is made. Keep needs: repro and the existing #2202 qualification relationship.

Dominant language
TypeScript
Stars
3
Forks
0
Avg merge
5h 8m
Merged PRs (30d)
946

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from schlessera/brain-kit

All issues in schlessera/brain-kit

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.