vuejs/core · error · Error
[@vue/compiler-sfc] `modules` option can only be used with c
Error message
[@vue/compiler-sfc] `modules` option can only be used with compileStyleAsync().
What it means
Thrown by doCompileStyle in @vue/compiler-sfc when the `modules` option is used with the synchronous compileStyle() entry point. postcss-modules resolves asynchronously (it writes a JSON map via getJSON), so Vue requires the caller to use compileStyleAsync and to set options.isAsync. The guard at compileStyle.ts:129 fires after the browser-build check, before postcssModules is registered.
Source
Thrown at packages/compiler-sfc/src/compileStyle.ts:129
const longId = `data-v-${shortId}`
const plugins = (postcssPlugins || []).slice()
plugins.unshift(cssVarsPlugin({ id: shortId, isProd }))
if (trim) {
plugins.push(trimPlugin())
}
if (scoped) {
plugins.push(scopedPlugin(longId))
}
let cssModules: Record<string, string> | undefined
if (modules) {
if (__GLOBAL__ || __ESM_BROWSER__) {
throw new Error(
'[@vue/compiler-sfc] `modules` option is not supported in the browser build.',
)
}
if (!options.isAsync) {
throw new Error(
'[@vue/compiler-sfc] `modules` option can only be used with compileStyleAsync().',
)
}
plugins.push(
postcssModules({
...modulesOptions,
getJSON: (_cssFileName: string, json: Record<string, string>) => {
cssModules = json
},
}),
)
}
const postCSSOptions: ProcessOptions = {
...postcssOptions,
to: filename,
from: filename,
}View on GitHub (pinned to a2b40db9a8)
Solutions
- Switch to compileStyleAsync() and await its result when you need CSS Modules.
- If you do not actually need CSS Modules, remove the `modules: true` option and keep using the sync compileStyle().
- In integration code, branch on the presence of the modules option to pick the correct entry point.
Example fix
// before
import { compileStyle } from '@vue/compiler-sfc'
const res = compileStyle({ filename: 'x.css', source, modules: true })
// after
import { compileStyleAsync } from '@vue/compiler-sfc'
const res = await compileStyleAsync({ filename: 'x.css', source, modules: true }) Defensive patterns
Strategy: validation
Validate before calling
// Route the modules option to the async entry automatically.
async function compileStyleSmart(opts) {
if (opts.modules) {
return compileStyleAsync({ ...opts, isAsync: true })
}
return compileStyle(opts)
} Type guard
function needsAsyncCompile(opts: unknown): opts is { modules: true } {
return !!opts && (opts as any).modules === true
} Prevention
- Always use compileStyleAsync when your options may include modules.
- Branch your wrapper on the modules flag so the sync entry is never used for CSS Modules.
- Treat `modules: true` as an async contract in your pipeline.
When it happens
Trigger: Calling compileStyle({ modules: true }) (the sync function) instead of compileStyleAsync({ modules: true }). Using any wrapper that internally calls the sync compileStyle while forwarding a modules flag.
Common situations: Migrating a style pipeline from sync to async but forgetting to switch the entry function; a custom integration that re-exports compileStyle under a different name.
Related errors
- [@vue/compiler-sfc] `modules` option is not supported in the
- [@vue/compiler-sfc] <script> and <script setup> must have th
- [@vue/compiler-sfc] SFC contains no <script> tags.
- [@vue/compiler-sfc] Style preprocessing in the browser build
- [@vue/compiler-sfc] Template preprocessing in the browser bu
AI-assisted analysis of vuejs/core@a2b40db9a8 (2026-08-12).
Data as JSON: /api/errors/24f3e196e668b9f3.
Report an issue: GitHub.