vuejs/core · error · Error
[@vue/compiler-sfc] SFC contains no <script> tags.
Error message
[@vue/compiler-sfc] SFC contains no <script> tags.
What it means
Thrown by compileScript in @vue/compiler-sfc when the SFC has neither a <script setup> nor a normal <script> block. compileScript exists to transform script blocks; with nothing to transform it cannot produce a component module. The guard at compileScript.ts:197 fires inside the !scriptSetup / !script branch.
Source
Thrown at packages/compiler-sfc/src/compileScript.ts:197
const { script, scriptSetup, source, filename } = sfc
const hoistStatic = options.hoistStatic !== false && !script
const scopeId = options.id ? options.id.replace(/^data-v-/, '') : ''
const scriptLang = script && script.lang
const scriptSetupLang = scriptSetup && scriptSetup.lang
const isJSOrTS =
isJS(scriptLang, scriptSetupLang) || isTS(scriptLang, scriptSetupLang)
if (script && scriptSetup && scriptLang !== scriptSetupLang) {
throw new Error(
`[@vue/compiler-sfc] <script> and <script setup> must have the same ` +
`language type.`,
)
}
if (!scriptSetup) {
if (!script) {
throw new Error(`[@vue/compiler-sfc] SFC contains no <script> tags.`)
}
// normal <script> only
if (script.lang && !isJSOrTS) {
// do not process non js/ts script blocks
return script
}
const ctx = new ScriptCompileContext(sfc, options)
return processNormalScript(ctx, scopeId)
}
if (scriptSetupLang && !isJSOrTS) {
// do not process non js/ts script blocks
return scriptSetup
}
const ctx = new ScriptCompileContext(sfc, options)View on GitHub (pinned to a2b40db9a8)
Solutions
- If the SFC is intentionally script-less, skip compileScript and rely on compileTemplate/compileStyle only.
- Add a <script setup> block (even an empty one) to give the SFC a component module.
- In build-tool integration code, gate the compileScript call on sfc.script || sfc.scriptSetup before invoking it.
- Verify the SFC source was not corrupted by a preprocessor that removed the script block.
Example fix
// before
<template><div>hi</div></template>
<style>.x{}</style>
// after
<template><div>hi</div></template>
<script setup lang="ts"></script>
<style>.x{}</style> Defensive patterns
Strategy: validation
Validate before calling
// Only call compileScript when there is something to compile.
function shouldCompileScript(sfc: { script?: unknown; scriptSetup?: unknown }) {
return !!(sfc.script || sfc.scriptSetup)
}
// usage:
if (shouldCompileScript(sfc)) {
compileScript(sfc, opts)
} Type guard
function sfcHasScript(sfc: { script?: unknown; scriptSetup?: unknown }): boolean {
return Boolean(sfc?.script || sfc?.scriptSetup)
} Prevention
- Gate compileScript on the presence of a script block in build-tool integration code.
- Document which .vue files are expected to be template/style-only.
- Validate SFC structure right after parse() and before compileScript().
When it happens
Trigger: Calling compileScript() on an SFC whose source only contains <template> and/or <style>; passing an SFC descriptor that was parsed from a template-only or style-only file.
Common situations: A genuinely script-less SFC being fed through a codegen pipeline that assumes a script block; a build tool (Vite plugin, vue-loader) invoking compileScript unconditionally for every .vue file including ones intended to be template/style only; a malformed SFC where the script tag was stripped by a preprocessor.
Related errors
- [@vue/compiler-sfc] <script> and <script setup> must have th
- [@vue/compiler-sfc] `modules` option is not supported in the
- [@vue/compiler-sfc] `modules` option can only be used with c
- [@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/d541ae0630038198.
Report an issue: GitHub.