LearnNewsExamplesServices
Frontmatter
id19898
titleA vessel closed mid-boot leaves its tear-out slot bound to a dead window
stateClosed
labels
bugaidashboard
assigneesneo-opus-grace
createdAtOct 20, 2026, 1:07 PM
updatedAtOct 20, 2026, 6:31 PM
githubUrlhttps://github.com/neomjs/neo/issues/19898
authorneo-opus-grace
commentsCount1
parentIssue19655
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 20, 2026, 6:31 PM

A vessel closed mid-boot leaves its tear-out slot bound to a dead window

Closed Backlog/active-chunk-9 bugaidashboard
neo-opus-grace
neo-opus-grace commented on Oct 20, 2026, 1:07 PM

Context

The Workstation film tour (WorkstationFilmTourNL, both arms) has been quarantined since 2026-10-12 as "hosted only: the tour stops at journey hop 3 because no fresh vessel is born" (accountable: me). A read-only diagnosis of the hop-level [film-probe] logs (runs 38258413156, 38260376912, 38271163182, 38276837825, 38291757581; 12 arm attempts) found two failure modes. This ticket is mode A (5 arms, 4 of them autoGates):

journey hop 3 (desktop): no fresh vessel was born — isWindowDragging=false reattachArmed=true lastRatio=0 vesselOpen={…"stage":"granted"} connects=false … activeVessel=false. No popup is created for the hop at all.

Every leg between main and the desktop point crosses Metrics' window. That window claims the drag, the vessel retires, and leaving reopens it, so a journey births 6 popups, 3 of them short-lived. In all 5 mode-A arms, hop 1's reopened vessel closed 0.41–0.47 s after creation. Every arm that closed it within 0.38 s went on to birth hop 3's vessel.

The Problem (inferred, ~60–70 %)

acquire returns null at reserve (src/manager/transaction/NativeLifecycle.mjs ~197–198), which refuses a slot with a live binder (src/manager/Transaction.mjs ~852). Every generation uses the same per-item key (apps/workstation/view/VesselWorkspace.mjs ~58–68). The binder can stay live past the window's death:

  • App#registerApp binds the slot before it sends registerAppName (src/worker/App.mjs ~897–898);
  • DomEvents#onBeforeUnload sends disconnect only for Manager.appNames (src/main/DomEvents.mjs ~485–486).

A popup closed between those two steps never disconnects, and nothing retries: the exit fires only while the pointer is moving out (src/draggable/container/SortZone.mjs ~388–400). For a user, a vessel closed quickly can leave that item unable to tear out again in the session.

The Fix

  1. First, confirm. Add the key's binding windowId and its port liveness to the gesture driver's diag() (apps/workstation/tour/NativeGestureDriver.mjs ~1414), and run hosted once with reporter output kept, or locally under 6× CPU throttling. A null binding at failure falsifies this cause.
  2. DomEvents#onBeforeUnload: when appNames is empty, send a window-scoped disconnect that worker/Base#onDisconnect (~559) accepts.
  3. App#registerApp: skip Transaction.admit when the window's port is already gone (importApp is async, so registration can follow the disconnect).

Acceptance Criteria

  • AC-1: The diag names the slot's binder and its liveness at a hop failure.
  • AC-2: A vessel closed between registerApp and registerAppName leaves its slot free: a unit or e2e arm, red before and green after.
  • AC-3: Moved to #19919. The first hosted run with this fix (#19918, job 118662525686) stopped the autoGates arm once at hop 4 with binder=null themeFileLoads=0, a third cause, and timed out its shard; the film arms stay quarantined until #19919 lands.

Out of Scope

Mode B (hop 4 target never settles; the viewer arm) is a separate ticket.

Related

Parent #19655.

Sweeps at 11:00Z: live latest-20 open issues, A2A claims (none).

Origin Session ID: 1cc54e4a-b230-43bc-ac83-7519d425f6e7

tobiu referenced in commit 0606987 - "fix(worker): a window that closes mid-boot frees its tear-out slot and its theme loads (#19898) (#19918) on Oct 20, 2026, 6:31 PM
tobiu closed this issue on Oct 20, 2026, 6:31 PM