pbakaus/impeccable · error · Error

[impeccable] the offscreen document has no live page; load a

Error message

[impeccable] the offscreen document has no live page; load a snapshot first

What it means

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.

Source

Thrown at crates/bundle/src/lib.rs:215

  return bytes;
}
let __impeccable = null;
let __impeccableInitError = null;
try {
  wasm_bindgen.initSync({ module: __impeccableWasmBytes() });
  __impeccable = wasm_bindgen;
} catch (e) {
  __impeccableInitError = e;
}
"#;

/// The offscreen document's core loader: fetch the module beside the script
/// and instantiate asynchronously (the extension's own CSP carries
/// 'wasm-unsafe-eval'). Also stubs the live-page probe namespace the glue
/// imports, so a call that would need a page fails loudly instead of with a
/// ReferenceError.
const EXT_CORE_LOADER: &str = r#"const __impeccableDom = new Proxy({}, {
  get() { throw new Error('[impeccable] the offscreen document has no live page; load a snapshot first'); },
});
async function __impeccableLoadCore() {
  await wasm_bindgen({ module_or_path: chrome.runtime.getURL('detector/core_bg.wasm') });
  return wasm_bindgen;
}
"#;

/// The capture contract: the property and state lists in `15-snapshot.js`
/// must equal the core's (`STYLE_PROPS`, `PSEUDO_PROPS` in snapshot.rs;
/// `STATE_PSEUDOS` in selector.rs), or a rule reads a column the capture did
/// not write. Returns the mismatch report on drift.
pub fn check_capture_contract() -> Result<(), String> {
    let snapshot_js = page_js("15-snapshot.js").expect("15-snapshot.js embedded");
    fn js_list(src: &str, name: &str) -> Vec<String> {
        let start = src
            .find(&format!("const {name} = ["))
            .unwrap_or_else(|| panic!("15-snapshot.js: {name} not found"));
        let rest = &src[start..];

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Load a snapshot first (send the scan message with msg.snapshot so snapshot_load runs) before any finding collection
  2. Use the snapshot-based IO methods (node, handle, parentOrBody, media) instead of direct DOM probes in offscreen code
  3. Move live-DOM probing to the content script and pass its results in the snapshot

Example fix

// before (offscreen)
const el = __impeccableDom.getElementById(id); // throws
// after
const el = IO.handle(id); // resolves through the loaded snapshot
Defensive patterns

Strategy: type-guard

Validate before calling

// Ensure a snapshot is loaded before any page-probing call in offscreen code
if (!snapshotLoaded) throw new Error('load a snapshot via snapshot_load before probing');

Type guard

function snapshotIsLoaded(state) { return typeof state.loadedNodeId === 'number' && state.loadedNodeId !== 0; }

Try / catch

try {
  probeLivePage(id);
} catch (e) {
  if (String(e.message).includes('no live page')) {
    // switch to snapshot-based lookup: IO.handle(id) / IO.parentOrBody(id)
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/429f4cff573be286. Report an issue: GitHub.