vitejs/vite · error · Error
?url is not supported with CSS modules.
Error message
?url is not supported with CSS modules. (tried to import ${id}) What it means
Thrown by the CSS plugin's load handler when a request combines the `?url` query (asking for the asset URL string) with a CSS Module request (a `.module.css`-style id). Vite does not support emitting CSS modules as plain URL assets; the two features are mutually exclusive. css.ts:361 throws before any further handling.
Solutions
- Drop the `?url` suffix when importing a CSS module: `import styles from './foo.module.css'`.
- If you need the URL, rename the file to a plain `.css` (non-module) and keep `?url`.
- Import the CSS module for its class map and import a separate plain CSS file for the URL asset.
- Audit codemods/aliases that append `?url` to CSS imports.
Example fix
// before import imgUrl from './Button.module.css?url' // after (use the module normally) import styles from './Button.module.css'
Defensive patterns
Strategy: validation
Validate before calling
const CSS_MODULE_RE = /\.module\.(css|scss|sass|less|styl)$/i
function assertNotCssModuleWithUrl(id: string) {
if (/\?url($|&)/.test(id) && CSS_MODULE_RE.test(id)) {
throw new Error(`Refusing to import ${id}: ?url is not supported with CSS modules.`)
}
} Type guard
function isCssModuleUrlCombo(id: string): boolean {
return /\?url($|&)/.test(id) && /\.module\.(css|scss|sass|less|styl)$/i.test(id)
} Try / catch
try {
await build()
} catch (e) {
if (e instanceof Error && /\?url is not supported with CSS modules/.test(e.message)) {
console.error('Remove ?url from CSS module imports; use a plain .css file for URL assets.')
}
throw e
} Prevention
- Lint imports to forbid combining `.module.*` with `?url`.
- Codemod `?url` off any stylesheet converted to a CSS module.
- Use a plain `.css` file when you need `?url`.
When it happens
Trigger: Source code does `import url from './foo.module.css?url'`. `urlRE.test(id)` is true and `isModuleCSSRequest(id)` (matches the `.module.css`/CSS-modules naming convention) is also true at css.ts:360, triggering the throw.
Common situations: Copy-pasting a `?url` import from a regular `.css` file onto a `.module.css` file. Migrating a stylesheet to CSS modules and forgetting to remove `?url`. Tooling that auto-appends `?url` to all CSS imports.
Related errors
- Cannot import non-asset file
- Failed to load PostCSS config
- Name in package.json is required if option…
- Preprocessor dependency
- " } is not supported for assets in files
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/105b5d47c744b5a5.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vite/src/node/plugins/css.ts:361
)
preprocessorWorkerControllerCache.set(
config,
preprocessorWorkerController,
)
},
async buildEnd() {
await preprocessorWorkerController?.close()
},
load: {
filter: {
id: CSS_LANGS_RE,
},
handler(id) {
if (urlRE.test(id)) {
if (isModuleCSSRequest(id)) {
throw new Error(
`?url is not supported with CSS modules. (tried to import ${JSON.stringify(
id,
)})`,
)
}
// *.css?url
// in dev, it's handled by assets plugin.
if (isBuild) {
id = injectQuery(removeUrlQuery(id), 'transform-only')
return (
`import ${JSON.stringify(id)};` +
`export default "__VITE_CSS_URL__${Buffer.from(id).toString(
'hex',
)}__"`
)
}
}View on GitHub (pinned to b4d66fee14)