pbakaus/impeccable · warning

[impeccable] visual contrast scan failed

Error message

[impeccable] visual contrast scan failed

What it means

Warning logged when the impeccable in-page visual contrast scan throws. The scan results already include the error message, and in extension mode the error is forwarded via postExtensionError; otherwise it is printed with console.warn. The page analysis completes without contrast data for the failed portion.

Source

Thrown at crates/live/assets/detect-antipatterns-browser.js:3604

  function postExtensionError(err) {
    if (!EXTENSION_MODE) return;
    window.postMessage({
      source: 'impeccable-error',
      message: err?.message || String(err),
    }, '*');
  }

  function reportVisualContrastError(err, detail = {}) {
    window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-error', {
      detail: {
        ...detail,
        message: err?.message || String(err),
      },
    }));
    if (EXTENSION_MODE) {
      postExtensionError(err);
    } else {
      console.warn('[impeccable] visual contrast scan failed', err);
    }
  }

  function scheduleLazyVisualContrast(groupMap, analyses, options = {}, runtime = {}) {
    disconnectLazyVisualContrastObserver();
    if (options.visualContrastLazy === false || options.scrollOffscreen !== false) return;
    if (typeof IntersectionObserver === 'undefined') return;
    const unresolved = __lazyVisualContrastCandidates(analyses);
    if (unresolved.length === 0) return;
    const generation = runtime.generation || scanGeneration;

    lazyVisualContrastObserver = new IntersectionObserver((entries) => {
      for (const entry of entries) {
        if (!entry.isIntersecting) continue;
        const el = entry.target;
        const candidate = lazyVisualContrastPending.get(el);
        if (!candidate || lazyVisualContrastResolving.has(el)) continue;
        lazyVisualContrastObserver?.unobserve(el);

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Read the accompanying err.message in the scan results or console to identify the throwing sub-step.
  2. Re-run the scan after DOM changes settle (images/fonts loaded, animations stopped).
  3. If it persists in extension mode, check the extension console via postExtensionError output; otherwise file the error with the page URL.
Defensive patterns

Strategy: try-catch

Validate before calling

if (!document.documentElement) return; // page not ready for a contrast scan

Type guard

function canScan(root) { return root instanceof Document || root instanceof Element; }

Try / catch

try {
  await runVisualContrastScan();
} catch (err) {
  reportScanError(err); // postExtensionError(err) in extension mode, console.warn otherwise
}

Prevention

When it happens

Trigger: The visual contrast analysis routine (getComputedStyle walks, canvas-based color checks, or lazy offscreen measurement) throws at runtime during scan() or its scheduled lazy pass.

Common situations: Pages with cross-origin iframes or shadow DOM the scanner cannot reach, elements removed mid-scan causing null access, canvas tainting, or browser APIs unavailable in restricted contexts.

Related errors


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