pbakaus/impeccable · warning
impeccable detect: could not read linked stylesheet {href} (
Error message
impeccable detect: could not read linked stylesheet {href} (resolved to {css_path}); color and custom-property rules will be incomplete\n What it means
During static detection, collect_static_css_text resolves each <link rel=stylesheet> href against the HTML file's location and reads it from disk to gather color and custom-property rules. When the file cannot be read (missing file, path outside the provided root, unreadable permissions), it emits this warning once per stylesheet (deduplicated via warned_missing_stylesheets) and continues with incomplete CSS, meaning color/contrast and custom-property based checks may be missed for that stylesheet.
Source
Thrown at crates/html/src/cascade/build.rs:124
let file_dir_str = file_dir.to_string_lossy().into_owned();
for link in doc.query_selector_all("link") {
let rel = link.get_attribute("rel").unwrap_or("");
let href = link.get_attribute("href").unwrap_or("");
if !STYLESHEET_REL_RE.is_match(rel) || href.is_empty() || REMOTE_HREF_RE.is_match(href) {
continue;
}
let css_path = resolve_linked_css_path(&file_dir_str, href);
let read = profile::step(
profile,
Meta::new("preprocess", "inline-linked-stylesheet", file_path).with_detail(href),
|| std::fs::read(&css_path),
);
match read {
Ok(bytes) => style_texts.push(String::from_utf8_lossy(&bytes).into_owned()),
Err(_) => {
if warned_missing_stylesheets.insert(css_path.clone()) {
if let Some(warn) = warn {
warn(&format!(
"impeccable detect: could not read linked stylesheet {href} (resolved to {css_path}); color and custom-property rules will be incomplete\n"
));
}
}
}
}
}
style_texts.join("\n")
}
static PSEUDO_RULE_RE: Lazy<Regex> = Lazy::new(|| {
Regex::new(&format!(
r"(?i)^(.+?){ws}*::?(?:before|after)$",
ws = js::WS
))
.expect("PSEUDO_RULE_RE")
});
static COLOR_TOKEN_RE: Lazy<Regex> = Lazy::new(|| {View on GitHub (pinned to 2bc2879276)
Solutions
- Run detection from a directory where the linked stylesheets actually exist relative to the HTML file (include the CSS assets, not just the HTML)
- Verify each <link href> resolves on disk from the HTML's own location; fix stale or hash-renamed hrefs by rebuilding first
- Serve/analyze built output: run the build before detection so referenced CSS files are emitted
- If the stylesheet is intentionally unavailable, treat this as a warning and supply the CSS another way (inline critical CSS or pass the stylesheet explicitly if the API supports it)
Example fix
<!-- before: href points at a file that does not exist next to the analyzed HTML --> <link rel="stylesheet" href="/css/main.css"> <!-- after: href resolves relative to the HTML file on disk --> <link rel="stylesheet" href="./css/main.css">
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs';
import { resolve, dirname } from 'node:path';
import { parseHTML } from 'linkedom';
function missingStylesheets(htmlPath) {
const html = readFileSync(htmlPath, 'utf8');
const { document } = parseHTML(html);
const base = dirname(htmlPath);
return [...document.querySelectorAll('link[rel="stylesheet"]')]
.map(l => resolve(base, l.getAttribute('href')))
.filter(p => { try { readFileSync(p); return false; } catch { return true; } });
} Type guard
function stylesheetExists(href, baseDir) {
const p = resolve(baseDir, href);
try { return readFileSync(p).length > 0; } catch { return false; }
} Try / catch
try {
const report = detect_html_source(html, { root: projectDir });
} catch (err) {
if (String(err).includes('could not read linked stylesheet')) {
console.warn('Some CSS was unreadable; color checks may be incomplete');
} else {
throw err;
}
} Prevention
- Always pass the HTML file together with its CSS assets in the same relative layout as the built site
- Run the project build before static detection so hashed/renamed CSS files exist
- Dry-run href resolution (resolve + fs.access) for every <link rel=stylesheet> before invoking detection
- When warnings list unreadable stylesheets, fix paths rather than ignoring them — color/custom-property rules drive several checks
When it happens
Trigger: Running impeccable detect on an HTML file that references stylesheets via absolute or relative paths that don't resolve under the detection root; the linked CSS file was moved/renamed/deleted; href points to a remote URL or a path outside the sandbox the detector is allowed to read; build output not generated before running detection.
Common situations: Pointing the CLI at extracted/single HTML files without the accompanying CSS assets; analyzing dist/ before a build has emitted linked CSS; hrefs rewritten by bundlers (hash-named files that no longer exist); running detection from a different working directory than expected so relative resolution lands elsewhere.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Warning: cannot access {target}
- Install failed: {e}
- Update failed: {e}
- Could not write the impeccable engine v{version} ({os}-{arch
AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08).
Data as JSON: /api/errors/ba3d57799dad9c01.
Report an issue: GitHub.