{"record":{"id":"429f4cff573be286","repo":"pbakaus/impeccable","slug":"impeccable-the-offscreen-document-has-no-live-pa","errorCode":null,"errorMessage":"[impeccable] the offscreen document has no live page; load a snapshot first","messagePattern":"\\[impeccable\\] the offscreen document has no live page; load a snapshot first","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/bundle/src/lib.rs","lineNumber":215,"sourceCode":"  return bytes;\n}\nlet __impeccable = null;\nlet __impeccableInitError = null;\ntry {\n  wasm_bindgen.initSync({ module: __impeccableWasmBytes() });\n  __impeccable = wasm_bindgen;\n} catch (e) {\n  __impeccableInitError = e;\n}\n\"#;\n\n/// The offscreen document's core loader: fetch the module beside the script\n/// and instantiate asynchronously (the extension's own CSP carries\n/// 'wasm-unsafe-eval'). Also stubs the live-page probe namespace the glue\n/// imports, so a call that would need a page fails loudly instead of with a\n/// ReferenceError.\nconst EXT_CORE_LOADER: &str = r#\"const __impeccableDom = new Proxy({}, {\n  get() { throw new Error('[impeccable] the offscreen document has no live page; load a snapshot first'); },\n});\nasync function __impeccableLoadCore() {\n  await wasm_bindgen({ module_or_path: chrome.runtime.getURL('detector/core_bg.wasm') });\n  return wasm_bindgen;\n}\n\"#;\n\n/// The capture contract: the property and state lists in `15-snapshot.js`\n/// must equal the core's (`STYLE_PROPS`, `PSEUDO_PROPS` in snapshot.rs;\n/// `STATE_PSEUDOS` in selector.rs), or a rule reads a column the capture did\n/// not write. Returns the mismatch report on drift.\npub fn check_capture_contract() -> Result<(), String> {\n    let snapshot_js = page_js(\"15-snapshot.js\").expect(\"15-snapshot.js embedded\");\n    fn js_list(src: &str, name: &str) -> Vec<String> {\n        let start = src\n            .find(&format!(\"const {name} = [\"))\n            .unwrap_or_else(|| panic!(\"15-snapshot.js: {name} not found\"));\n        let rest = &src[start..];","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/crates/bundle/src/lib.rs#L197-L233","documentation":"In the offscreen document the live-page DOM probe namespace (__impeccableDom) is intentionally stubbed with a Proxy whose every property get throws this error. Any glue call that would need the real page (instead of a loaded snapshot) fails loudly and explicitly rather than with a ReferenceError.","triggerScenarios":"Running page-probing calls (document/element queries routed through the __impeccableDom proxy) inside the extension's offscreen document before/instead of loading a snapshot via snapshot_load.","commonSituations":"Invoking a detection pass that mixes live-DOM probes with snapshot analysis from the offscreen context; a code path forgot to route element lookups through the snapshot media/parent APIs.","solutions":["Load a snapshot first (send the scan message with msg.snapshot so snapshot_load runs) before any finding collection","Use the snapshot-based IO methods (node, handle, parentOrBody, media) instead of direct DOM probes in offscreen code","Move live-DOM probing to the content script and pass its results in the snapshot"],"exampleFix":"// before (offscreen)\nconst el = __impeccableDom.getElementById(id); // throws\n// after\nconst el = IO.handle(id); // resolves through the loaded snapshot","handlingStrategy":"type-guard","validationCode":"// Ensure a snapshot is loaded before any page-probing call in offscreen code\nif (!snapshotLoaded) throw new Error('load a snapshot via snapshot_load before probing');","typeGuard":"function snapshotIsLoaded(state) { return typeof state.loadedNodeId === 'number' && state.loadedNodeId !== 0; }","tryCatchPattern":"try {\n  probeLivePage(id);\n} catch (e) {\n  if (String(e.message).includes('no live page')) {\n    // switch to snapshot-based lookup: IO.handle(id) / IO.parentOrBody(id)\n  }\n}","preventionTips":["In offscreen code, never touch __impeccableDom; use snapshot IO helpers","Always run snapshot_load before collecting findings offscreen","Move any live-DOM probing into the content script and ship results in the snapshot"],"tags":["offscreen","browser-extension","snapshot"],"backgroundTag":"invalid-state-transition","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}