vuejs/vue · 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 @vue/compiler-sfc's compileScript() when the SFC descriptor passed in has neither a <script> nor a <script setup> block. The compiler needs at least one script block to produce bindings and script AST metadata; without one it cannot proceed. This indicates either a malformed SFC or that compileScript was invoked on a descriptor produced from a template-only or style-only .vue file.

Source

Thrown at packages/compiler-sfc/src/compileScript.ts:138

    plugins.push('jsx')
  } else {
    // If don't match the case of adding jsx, should remove the jsx from the babelParserPlugins
    if (options.babelParserPlugins)
      options.babelParserPlugins = options.babelParserPlugins.filter(
        n => n !== 'jsx'
      )
  }
  if (options.babelParserPlugins) plugins.push(...options.babelParserPlugins)
  if (isTS) {
    plugins.push('typescript')
    if (!plugins.includes('decorators')) {
      plugins.push('decorators-legacy')
    }
  }

  if (!scriptSetup) {
    if (!script) {
      throw new Error(`[@vue/compiler-sfc] SFC contains no <script> tags.`)
    }
    if (scriptLang && !isTS && scriptLang !== 'jsx') {
      // do not process non js/ts script blocks
      return script
    }
    try {
      let content = script.content
      let map = script.map
      const scriptAst = _parse(content, {
        plugins,
        sourceType: 'module'
      }).program
      const bindings = analyzeScriptBindings(scriptAst.body)
      if (cssVars.length) {
        content = rewriteDefault(content, DEFAULT_VAR, plugins)
        content += genNormalScriptCssVarsCode(
          cssVars,
          bindings,

View on GitHub (pinned to 9e88707940)

Solutions

  1. Check the SFC descriptor before calling compileScript: if (!descriptor.script && !descriptor.scriptSetup) skip compilation and return early.
  2. Add a <script> or <script setup> block to the .vue file, even an empty export default {} is sufficient.
  3. If the file is intentionally script-less, route it through compileTemplate/compileStyle instead of compileScript.

Example fix

// before
const script = compileScript(descriptor, { id: 'data-v-xxx' })

// after
if (!descriptor.script && !descriptor.scriptSetup) {
  throw new Error(`${descriptor.filename} has no <script> block; nothing to compile`)
}
const script = compileScript(descriptor, { id: 'data-v-xxx' })
Defensive patterns

Strategy: validation

Validate before calling

import type { SFCDescriptor } from '@vue/compiler-sfc'

function canCompileScript(descriptor: SFCDescriptor): boolean {
  return Boolean(descriptor.script || descriptor.scriptSetup)
}

// before calling compileScript:
if (!canCompileScript(descriptor)) {
  console.warn(`${descriptor.filename}: no <script> block, skipping compileScript`)
  return null
}
const script = compileScript(descriptor, { id: 'data-v-xxx' })

Type guard

function hasScriptBlock(descriptor: SFCDescriptor): descriptor is SFCDescriptor & { script: SFCScriptBlock } {
  return descriptor.script != null
}

function hasScriptSetup(descriptor: SFCDescriptor): descriptor is SFCDescriptor & { scriptSetup: SFCScriptBlock } {
  return descriptor.scriptSetup != null
}

Try / catch

try {
  const script = compileScript(descriptor, opts)
} catch (e) {
  if (e.message.includes('SFC contains no <script> tags')) {
    // script-less SFC: skip compilation gracefully
    return null
  }
  throw e
}

Prevention

When it happens

Trigger: Calling compileScript(descriptor, { id }) where descriptor.script and descriptor.scriptSetup are both null/undefined. This happens when a .vue file contains only <template> and/or <style> blocks, when parseComponent was given empty source, or when an integration (e.g. vue-loader plugin) routes a non-script SFC through compileScript.

Common situations: A toolchain or custom build plugin unconditionally calls compileScript on every SFC descriptor. Template-only or style-only components (rare but valid for some design-system use cases) hit this. Also triggered when an SFC is generated programmatically and the <script> tag is omitted or stripped.

Related errors


AI-assisted analysis of vuejs/vue@9e88707940 (2026-08-11). Data as JSON: /api/errors/85e1abe32bd97418. Report an issue: GitHub.