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") || undefined

View on GitHub (pinned to 6beaca3952)

Solutions

  1. Hard-refresh the page; if it persists, restart `react-router dev` to rebuild the Vite module graph
  2. Open the exact file named in the warning and fix any CSS/PostCSS syntax error or bad @import/url() it contains
  3. Clear the Vite cache: `rm -rf node_modules/.vite`, then restart dev
  4. 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

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


AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18). Data as JSON: /api/errors/08bc4ac880ce478d. Report an issue: GitHub.