This is the successor to #18348, which PR #18353 closed. #18348 left one question open, and this ticket answers it with a local reproduction.
Context
component/tab/OverflowAction.spec.mjs:162 (renders first, outside focus gating, with measured non-overlap and ordinary menu activation) failed the components job in 15 of the last 25 failed Engine Tests runs, from 2026-09-08 to 09-14. Five of those failures were on dev: 34228960926, 34253760041, 34355808406, 34400460345 and 34580274841. Every failure looks the same: the overflow menu opens, its first item resolves, and the click times out because the item "was detached from the DOM".
#18348 bound the item by id, so the arm now fails naming it. Its open question stayed open: does the menu re-render after it is shown?
The Problem
The failure reproduces locally in Playwright Chromium with Emulation.setCPUThrottlingRate at 6. The arm's own steps fail 4 of 20 runs and 5 of 30 runs. A plain open-and-click without the arm's layout reads fails 0 of 20.
A DOM mutation trail recorded identically on all 5 failures (ms from when the observer attached; the control's pointerdown lands at about 38):
| ms |
mutation |
| ~44 |
+ tab header buttons 7 and 8 |
| ~89 |
+ neo-menu-list-1, mounted with records 1 and 2 |
| ~110 |
one batch: + records 3, 4 and 5; − records 1 and 2; − header buttons 6, 7 and 8 |
| ~176 |
− neo-menu-list-1 |
Reading the trail against the source: at ~44, the restored header buttons match #project's recapture, which restores hidden buttons so it can measure them. At ~110, one batch applies a new split with three tabs hidden and rewrites the open menu's items. The menu closes about 65 ms later. A user who clicks the control while a projection's measurement is still in flight hits the same window; throttling only widens it.
The Architectural Reality
Overflow#queueOpenMenuProjection (src/tab/plugin/Overflow.mjs) parks a projection only while menuList.mounted is true, and #project calls it again at the mutation boundary, just before applySplit.
button.Base#toggleMenu sets menuList.hidden = false synchronously. mounted turns true only after the shown menu's vnode has been inserted. A projection whose getDomRect resolves between those two moments passes both checks.
Overflow#syncControl then writes menuList.items for the changed signature. Its own idempotence note says a rewrite rebuilds the dropdown and closes it mid-interaction.
#restoreOpenMenuPartition runs on the menu's mounted edge. It already handles part of this case: a recapture that made hidden headers visible while the menu was opening.
The Fix
This is a candidate until the reproduction confirms it. Park while the menu is open or opening (menuList && !menuList.hidden) instead of only while it is mounted. A projection that resolves after the click then parks, and drains on the menu's unmount edge as it does today.
Acceptance Criteria
Out of Scope
- Header actions evicting tab buttons in narrow dock zones (#18693). That is the documented repartition, not this race.
- When projections run, and the menu's item rewrite outside the opening window.
Related
#18348 (predecessor) · PR #18353 · #18693 (same surface, different mechanism) · PR #17626 (introduced the open-menu park) · PR #18722 (the fix)
Decision Record impact: none.
Structure map: N/A. An existing plugin changes in place.
Live latest-open sweep: checked the latest 20 open issues at 2026-09-15T03:05Z. No equivalent; #18693 is adjacent, as noted above.
A2A in-flight claim sweep: checked the latest 30 messages in all read states. No claim covers the overflow plugin or this arm.
Memory Core rationale sweep: no prior decision on the parking window.
Own-assignment sweep: none of my open assignments covers this.
Origin Session ID: b9eefdf5-60e0-4156-860c-8cb4a628b8db
This is the successor to #18348, which PR #18353 closed. #18348 left one question open, and this ticket answers it with a local reproduction.
Context
component/tab/OverflowAction.spec.mjs:162(renders first, outside focus gating, with measured non-overlap and ordinary menu activation) failed thecomponentsjob in 15 of the last 25 failedEngine Testsruns, from 2026-09-08 to 09-14. Five of those failures were ondev: 34228960926, 34253760041, 34355808406, 34400460345 and 34580274841. Every failure looks the same: the overflow menu opens, its first item resolves, and the click times out because the item "was detached from the DOM".#18348 bound the item by id, so the arm now fails naming it. Its open question stayed open: does the menu re-render after it is shown?
The Problem
The failure reproduces locally in Playwright Chromium with
Emulation.setCPUThrottlingRateat 6. The arm's own steps fail 4 of 20 runs and 5 of 30 runs. A plain open-and-click without the arm's layout reads fails 0 of 20.A DOM mutation trail recorded identically on all 5 failures (ms from when the observer attached; the control's
pointerdownlands at about 38):+tab header buttons 7 and 8+neo-menu-list-1, mounted with records 1 and 2+records 3, 4 and 5;−records 1 and 2;−header buttons 6, 7 and 8−neo-menu-list-1Reading the trail against the source: at ~44, the restored header buttons match
#project's recapture, which restores hidden buttons so it can measure them. At ~110, one batch applies a new split with three tabs hidden and rewrites the open menu's items. The menu closes about 65 ms later. A user who clicks the control while a projection's measurement is still in flight hits the same window; throttling only widens it.The Architectural Reality
Overflow#queueOpenMenuProjection(src/tab/plugin/Overflow.mjs) parks a projection only whilemenuList.mountedis true, and#projectcalls it again at the mutation boundary, just beforeapplySplit.button.Base#toggleMenusetsmenuList.hidden = falsesynchronously.mountedturns true only after the shown menu's vnode has been inserted. A projection whosegetDomRectresolves between those two moments passes both checks.Overflow#syncControlthen writesmenuList.itemsfor the changed signature. Its own idempotence note says a rewrite rebuilds the dropdown and closes it mid-interaction.#restoreOpenMenuPartitionruns on the menu's mounted edge. It already handles part of this case: a recapture that made hidden headers visible while the menu was opening.The Fix
This is a candidate until the reproduction confirms it. Park while the menu is open or opening (
menuList && !menuList.hidden) instead of only while it is mounted. A projection that resolves after the click then parks, and drains on the menu's unmount edge as it does today.Acceptance Criteria
toggleMenushows the menu but before the menu mounts is parked. The open menu's items and the header partition stay untouched.devand passes 60/60 with the fix.OverflowAction.spec.mjspasses in full.Out of Scope
Related
#18348 (predecessor) · PR #18353 · #18693 (same surface, different mechanism) · PR #17626 (introduced the open-menu park) · PR #18722 (the fix)
Decision Record impact: none. Structure map: N/A. An existing plugin changes in place. Live latest-open sweep: checked the latest 20 open issues at 2026-09-15T03:05Z. No equivalent; #18693 is adjacent, as noted above. A2A in-flight claim sweep: checked the latest 30 messages in all read states. No claim covers the overflow plugin or this arm. Memory Core rationale sweep: no prior decision on the parking window. Own-assignment sweep: none of my open assignments covers this.
Origin Session ID: b9eefdf5-60e0-4156-860c-8cb4a628b8db