remix-run/react-router · warning
Failed to load CSS for ${dep.file}
Error message
Failed to load CSS for ${dep.file} What it means
During dev, React Router walks the Vite module graph to collect CSS for a route and calls loadCssContents per CSS dependency. If loading one fails, it logs `Failed to load CSS for <file>` and skips that stylesheet — the in-code comment attributes this to dynamically imported modules where the Vite module graph doesn't cleanly distinguish static from dynamic imports. The dev server keeps running; the symptom is missing styles until reload.
Source
Thrown at packages/react-router-dev/vite/styles.ts:105
continue;
}
await findDeps(viteDevServer, node, deps);
}
} catch (err) {
console.error(err);
}
for (let dep of deps) {
if (
dep.file &&
isCssFile(dep.file) &&
!isCssUrlWithoutSideEffects(dep.url) // Ignore styles that resolved as URLs, inline or raw. These shouldn't get injected.
) {
try {
styles[dep.url] = await loadCssContents(viteDevServer, dep);
} catch {
console.warn(`Failed to load CSS for ${dep.file}`);
// this can happen with dynamically imported modules, I think
// because the Vite module graph doesn't distinguish between
// static and dynamic imports? TODO investigate, submit fix
}
}
}
return (
Object.entries(styles)
.map(([fileName, css], i) => [
`\n/* ${fileName
// Escape comment syntax in file paths
.replace(/\/\*/g, "/\\*")
.replace(/\*\//g, "*\\/")} */`,
css,
])
.flat()
.join("\n") || undefinedView on GitHub (pinned to 6beaca3952)
Solutions
- Hard-refresh the page; if it persists, restart `react-router dev` to rebuild the Vite module graph
- Open the exact file named in the warning and fix any CSS/PostCSS syntax error or bad @import/url() it contains
- Clear the Vite cache: `rm -rf node_modules/.vite`, then restart dev
- If the file is only reached through a dynamic import, import the CSS statically in the route module so the module graph tracks it reliably
Example fix
// before - app/routes/dashboard.tsx
let mod = await import("./dashboard.lazy"); // dashboard.lazy imports its own CSS
// after
import "./dashboard.css"; // static import tracked by the Vite module graph
let mod = await import("./dashboard.lazy"); Defensive patterns
Strategy: retry
Validate before calling
// cheap pre-check: every CSS file referenced by route modules exists and parses as non-empty
import fs from "node:fs";
for (let file of cssImportsFromRouteModules()) {
if (!fs.existsSync(file)) throw new Error(`Missing CSS file: ${file}`);
if (fs.statSync(file).size === 0) console.warn(`Empty CSS file: ${file}`);
} Try / catch
// the framework already catches and warns per-dependency; mirror that in any
// custom style pipeline:
try { styles[dep.url] = await loadCss(dep); } catch { console.warn(`Failed to load CSS for ${dep.file}`); } Prevention
- Import route CSS statically in route modules; keep dynamic imports for JS only
- Keep PostCSS/Tailwind configs valid — CSS transform errors surface as this warning first
- When styles go missing in dev, restart the dev server and clear node_modules/.vite before debugging app code
When it happens
Trigger: Dev server running, a route's CSS dependency fails to load through the module graph: CSS reachable only via a dynamic `import()`, a transform error in that CSS file, or a stale module graph after adding/removing files.
Common situations: CSS imported inside `await import("./lazy.module.css")`; a PostCSS/Tailwind syntax error surfacing here first; HMR leaving the graph inconsistent; stale node_modules/.vite cache after dependency changes.
Related errors
- When using the React Router `basename` and the Vite `base` c
- React Router config loading requires Vite's __config_loader
- React Router Vite plugin not found in Vite config
- Custom Vite manifest paths are not supported
- The React Router Vite plugin requires the use of a Vite conf
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/08bc4ac880ce478d.
Report an issue: GitHub.