Observed live on Zen 153.0.1 (Firefox 153), signed install 0.2.0.2, driving the bridge from Gullet.
Sequence
>>> tabs_load {"tabIds":[1235]}
<<< {"tabs":[{"tabId":1235,"status":"ready","url":"https://transluce.org/"}],"ready":1,"pending":0,"failed":0}
>>> tab_clip {"tabId":1235,"vault":"test","close":true}
<<< ERROR {"error":"extract-failed","message":"Missing host permission for the tab"}
>>> tab_clip {"tabId":1235,"vault":"test","close":true} # identical call, seconds later
<<< (succeeded — extraction, clip, verification all fine)
Same tab, same URL, same session. The tab had been clipped successfully by this same install ~20 minutes earlier, so the permission was genuinely held throughout; nothing about the grant changed between the two calls.
Where the message comes from
It is not ours. readTab surfaces result.error verbatim (src/bridge-methods.ts:586), so this is Gecko's own scripting.executeScript rejection. The hasOrigins(CLIP_ORIGINS) check just above it passed — the extension does hold *://*/* — which is why it fell through to extract-failed rather than the not-enabled branch with its remedy text.
Note the tab had also passed both guards immediately before: isHttpUrl(tab.url) was true (so the URL had committed — not the about:blank case documented in AGENTS.md) and tab.discarded was false.
Hypothesis (not verified)
A window after tabs_load where the tab reports status: "complete" and a committed URL, but its principal is not yet the page's, so Gecko evaluates the host-permission check against the wrong principal. ensureTabReady resolves on onUpdated "complete", which may precede scriptability. Alternative: an unrelated transient in executeScript after a discard/reload cycle. The observation does not separate these.
Why it matters
Wake-then-clip is the batch triage flow the bridge exists for — tabs_load a batch of survivors, then clip them. A transient failure there makes that flow flaky, and the error text sends the reader after a permissions problem that does not exist. An agent seeing it would plausibly tell the user to re-grant site access, or skip the tab as unreadable.
Possible directions
- Retry
extract once on this specific rejection before reporting failure.
- Probe scriptability rather than trusting
status: "complete" — a trivial executeScript after the reload, the way ensureTabReady already owns readiness for both callers.
- At minimum, do not surface a raw engine string that names permissions when the permission check we can make has just passed; say the extraction failed transiently and suggest a retry.
Reproduction is intermittent — one failure in this session, on the first clip after a wake. Not seen without a preceding tabs_load.
Observed live on Zen 153.0.1 (Firefox 153), signed install 0.2.0.2, driving the bridge from Gullet.
Sequence
Same tab, same URL, same session. The tab had been clipped successfully by this same install ~20 minutes earlier, so the permission was genuinely held throughout; nothing about the grant changed between the two calls.
Where the message comes from
It is not ours.
readTabsurfacesresult.errorverbatim (src/bridge-methods.ts:586), so this is Gecko's ownscripting.executeScriptrejection. ThehasOrigins(CLIP_ORIGINS)check just above it passed — the extension does hold*://*/*— which is why it fell through toextract-failedrather than thenot-enabledbranch with its remedy text.Note the tab had also passed both guards immediately before:
isHttpUrl(tab.url)was true (so the URL had committed — not theabout:blankcase documented in AGENTS.md) andtab.discardedwas false.Hypothesis (not verified)
A window after
tabs_loadwhere the tab reportsstatus: "complete"and a committed URL, but its principal is not yet the page's, so Gecko evaluates the host-permission check against the wrong principal.ensureTabReadyresolves ononUpdated"complete", which may precede scriptability. Alternative: an unrelated transient inexecuteScriptafter a discard/reload cycle. The observation does not separate these.Why it matters
Wake-then-clip is the batch triage flow the bridge exists for —
tabs_loada batch of survivors, then clip them. A transient failure there makes that flow flaky, and the error text sends the reader after a permissions problem that does not exist. An agent seeing it would plausibly tell the user to re-grant site access, or skip the tab as unreadable.Possible directions
extractonce on this specific rejection before reporting failure.status: "complete"— a trivialexecuteScriptafter the reload, the wayensureTabReadyalready owns readiness for both callers.Reproduction is intermittent — one failure in this session, on the first clip after a wake. Not seen without a preceding
tabs_load.