{"record":{"id":"364a6d3adfd9283d","repo":"parcel-bundler/parcel","slug":"dynamic-diagnostic-from-vue-compiler-parse-errors","errorCode":null,"errorMessage":"[dynamic diagnostic from Vue compiler parse errors]","messagePattern":"\\[dynamic diagnostic from Vue compiler parse errors\\]","errorType":"exception","errorClass":"ThrowableDiagnostic","httpStatus":null,"severity":"error","filePath":"packages/transformers/vue/src/VueTransformer.js","lineNumber":70,"sourceCode":"    }\n    return {\n      customBlocks: contents.customBlocks || {},\n      filePath: conf && conf.filePath,\n      compilerOptions: contents.compilerOptions || {},\n    };\n  },\n  canReuseAST({ast}) {\n    return ast.type === 'vue' && semver.satisfies(ast.version, '^3.0.0');\n  },\n  async parse({asset, options}) {\n    // TODO: This parses the vue component multiple times. Fix?\n    let code = await asset.getCode();\n    let parsed = compiler.parse(code, {\n      sourceMap: true,\n      filename: asset.filePath,\n    });\n    if (parsed.errors.length) {\n      throw new ThrowableDiagnostic({\n        diagnostic: parsed.errors.map(err => {\n          return createDiagnostic(err, asset.filePath);\n        }),\n      });\n    }\n\n    const descriptor = parsed.descriptor;\n    let id = hashObject({\n      filePath: asset.filePath,\n      source: options.mode === 'production' ? code : null,\n    }).slice(-6);\n\n    return {\n      type: 'vue',\n      version: '3.0.0',\n      program: {\n        ...descriptor,\n        script:","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/parcel-bundler/parcel/blob/59484858a1a0bcbb71f74088956bb437a2db6505/packages/transformers/vue/src/VueTransformer.js#L52-L88","documentation":"Thrown by @parcel/transformer-vue when @vue/compiler-sfc's parse() returns a non-empty errors array for the component source. Each Vue compiler error is mapped through createDiagnostic (with the asset filePath) and wrapped in a ThrowableDiagnostic. This is the SFC-level parse stage (top-level <template>/<script>/<style> blocks), distinct from template/style compilation.","triggerScenarios":"compiler.parse(code, {sourceMap:true, filename}) is called on the asset code; malformed SFC structure (unclosed top-level tags, invalid block attributes, duplicate root blocks) populates parsed.errors.","commonSituations":"Unclosed <template> tag, a <script> and a second <script> without the setup/module split, custom block with malformed attributes, or an SFC written for Vue 2 loaded with the Vue 3 compiler (canReuseAST requires ^3.0.0).","solutions":["Open the .vue file and fix the structural error at the cited line.","Confirm the file is a valid Vue 3 single-file component (single root <template>, valid block tags).","Upgrade/downgrade @vue/compiler-sfc to match the project's Vue version.","Validate the SFC in the Vue SFC Playground to isolate the parse error."],"exampleFix":"// before\n<template><div>hi</template>\n// after\n<template><div>hi</div></template>","handlingStrategy":"validation","validationCode":"import { parse } from '@vue/compiler-sfc';\nconst { errors } = parse(code, { filename });\nif (errors.length) throw new Error('SFC parse errors: ' + errors.map(e => e.message).join('; '));","typeGuard":"function isValidSfc(code) {\n  return parse(code, { filename: 'x.vue' }).errors.length === 0;\n}","tryCatchPattern":"try {\n  await vueTransformer.parse({asset, options});\n} catch (e) {\n  if (e?.diagnostics?.some(d => /parse/i.test(d.message))) {\n    /* surface SFC structural error to the user */\n  }\n  throw e;\n}","preventionTips":["Validate .vue files in the Vue SFC Playground before committing.","Keep a single root <template> and well-formed block tags.","Match @vue/compiler-sfc version to your Vue major version."],"tags":["vue","sfc","parser","parcel-transformer"],"backgroundTag":null,"analyzedSha":"59484858a1a0bcbb71f74088956bb437a2db6505","analyzedAt":"2026-08-13T04:06:35.925Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}