LearnNewsExamplesServices
Frontmatter
id19067
titleA message for a departed window falls back to a sibling window of the same app
stateClosed
labels
bugaicore
assigneesneo-opus-grace
createdAtSep 23, 2026, 2:17 AM
updatedAtSep 23, 2026, 3:37 AM
githubUrlhttps://github.com/neomjs/neo/issues/19067
authorneo-opus-grace
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtSep 23, 2026, 3:37 AM

A message for a departed window falls back to a sibling window of the same app

neo-opus-grace
neo-opus-grace commented on Sep 23, 2026, 2:17 AM

Context

After a warm F5 in a two-root Workstation, the #17844 battery's WorkstationTopologyGroupsNL arms fail in 4 of 6 runs with App Worker: Error: Target worker '<uuid>' does not exist. This holds even with #19056's and #19060's fixes applied (recorded on #19060). The <uuid> is a window id, not a worker name. That text is thrown by the main thread's worker/Manager.mjs:612, and main relays any dest that is not itself to a worker of that name.

The Problem

worker.Base#sendMessage (SharedWorker branch, src/worker/Base.mjs) resolves a port through a cascade:

  1. getPort({windowId: dest}) || getPort({id: dest})
  2. then opts.port
  3. then opts.windowId
  4. then opts.appName

For a message addressed to a window that has departed, steps 1–3 miss and step 4 resolves a sibling window of the same app. The message then lands in that sibling's main thread with destination set to the departed window id. Main treats the id as a worker name and rejects, and the rejection returns to the App Worker as a failure attributed to the wrong window.

Reproduced on dev@58d69efa32 with a unit stub holding two ports of app App. After removePort(win-a), sendMessage('win-a', {appName: 'App', windowId: 'win-a', …}) posts to win-b (POSTED_TO_SIBLING 1).

The block's own last-resort comment names the hazard: "delivering a keyed message to an arbitrary port would misroute it into a foreign window". The appName step does exactly that for a departed window.

The Architectural Reality

  • The appName step exists for a real case: a stale opts.port between receipt and reply, where the same logical target re-registered.
  • isWindowDeparted(windowId) (#18741) already records departures at the instant removePort() runs.
  • #19056 / #19061 settle an unhandled NEO_DEAD_PORT whose window departed. Once the misroute stops, these messages become exactly that shape.

The Fix

Skip the appName step when the addressed window (opts.windowId ?? dest) is known to have departed. The send then resolves no port, and promiseMessage rejects NEO_DEAD_PORT with the window id: settled if nobody awaits it, visible to a caller that does. The step keeps serving a target that re-registered and never departed.

Acceptance Criteria

  • AC-1 — A unit arm: a message for a departed window is posted to no sibling and yields no message, so promiseMessage rejects NEO_DEAD_PORT with that windowId. Removing the guard turns it red.
  • AC-2 — Control arms keep today's behaviour:
    • a keyed message whose window never departed still falls back to the app's port;
    • a message for a live window still goes to that window.
  • AC-3 — With #19061 applied, whole-file WorkstationTopologyGroupsNL runs show no Target worker '<uuid>' does not exist line.

Out of Scope

  • The main thread's relay treating an unknown dest as a worker name. It becomes unreachable for window ids once nothing misroutes them.
  • Warm F5's remaining .reload-retained-witness visibility timeout.

Decision Record impact

None. The change is aligned with #18741's departure predicate and #19056's settlement.

Related

Sweeps: live latest-open at 2026-09-23T00:16Z; open issues for misroute sibling window, appName fallback port and Target worker does not exist: none beyond #19060 / #17844. A2A lane-claims (last 15): none on this. Own assignments: none overlapping.

Origin Session ID: 19051047-2f38-4bf0-be51-efd6b957564d

Retrieval Hint: query_raw_memories("departed window message appName fallback sibling port Target worker does not exist sendMessage cascade")

tobiu referenced in commit fff93f3 - "fix(worker): a message addressed to a departed window is not delivered to a sibling of its app (#19067) (#19074) on Sep 23, 2026, 3:37 AM
tobiu closed this issue on Sep 23, 2026, 3:37 AM