{"record":{"id":"fe093b89b952df58","repo":"pbakaus/impeccable","slug":"impeccable-visual-contrast-scan-failed-fe093b","errorCode":null,"errorMessage":"[impeccable] visual contrast scan failed","messagePattern":"\\[impeccable\\] visual contrast scan failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/live/assets/detect-antipatterns-browser.js","lineNumber":3604,"sourceCode":"  function postExtensionError(err) {\n    if (!EXTENSION_MODE) return;\n    window.postMessage({\n      source: 'impeccable-error',\n      message: err?.message || String(err),\n    }, '*');\n  }\n\n  function reportVisualContrastError(err, detail = {}) {\n    window.dispatchEvent(new CustomEvent('impeccable-visual-contrast-error', {\n      detail: {\n        ...detail,\n        message: err?.message || String(err),\n      },\n    }));\n    if (EXTENSION_MODE) {\n      postExtensionError(err);\n    } else {\n      console.warn('[impeccable] visual contrast scan failed', err);\n    }\n  }\n\n  function scheduleLazyVisualContrast(groupMap, analyses, options = {}, runtime = {}) {\n    disconnectLazyVisualContrastObserver();\n    if (options.visualContrastLazy === false || options.scrollOffscreen !== false) return;\n    if (typeof IntersectionObserver === 'undefined') return;\n    const unresolved = __lazyVisualContrastCandidates(analyses);\n    if (unresolved.length === 0) return;\n    const generation = runtime.generation || scanGeneration;\n\n    lazyVisualContrastObserver = new IntersectionObserver((entries) => {\n      for (const entry of entries) {\n        if (!entry.isIntersecting) continue;\n        const el = entry.target;\n        const candidate = lazyVisualContrastPending.get(el);\n        if (!candidate || lazyVisualContrastResolving.has(el)) continue;\n        lazyVisualContrastObserver?.unobserve(el);","sourceCodeStart":3586,"sourceCodeEnd":3622,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/crates/live/assets/detect-antipatterns-browser.js#L3586-L3622","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the accompanying err.message in the scan results or console to identify the throwing sub-step.","Re-run the scan after DOM changes settle (images/fonts loaded, animations stopped).","If it persists in extension mode, check the extension console via postExtensionError output; otherwise file the error with the page URL."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!document.documentElement) return; // page not ready for a contrast scan\n","typeGuard":"function canScan(root) { return root instanceof Document || root instanceof Element; }","tryCatchPattern":"try {\n  await runVisualContrastScan();\n} catch (err) {\n  reportScanError(err); // postExtensionError(err) in extension mode, console.warn otherwise\n}","preventionTips":["Run the scan after fonts/images load and DOM mutations settle.","Handle shadow DOM and cross-origin iframes explicitly instead of assuming access.","Keep a scan-results channel that includes err.message so failures are diagnosable, as the bundle does."],"tags":["scan","contrast","accessibility","browser"],"backgroundTag":"scan-failed","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}