quasarframework/quasar · error · Error
${message} at line ${lineNo} col ${colNo} (unclosed comment/
Error message
${message} at line ${lineNo} col ${colNo} (unclosed comment/unclosed string/unclosed tag) What it means
create-quasar's template.js parses scaffolding templates into an AST. When the EJS-style parser cannot close a comment, string, or tag before end-of-file, throwParseError builds a message showing the offending source line with a caret pointer and throws. It means a template asset inside create-quasar is malformed, not your project files.
Source
Thrown at create-quasar/lib/template.js:44
function throwParseError(message, str, index) {
const whitespace = str.slice(0, index).split(newlineRE)
const lineNo = whitespace.length
const colNo = whitespace[lineNo - 1].length + 1
message +=
' at line ' +
lineNo +
' col ' +
colNo +
':\n\n' +
' ' +
str.split(newlineRE)[lineNo - 1] +
'\n' +
' '.repeat(colNo + 1) +
'^'
throw new Error(message)
}
function escapeRegExp(str) {
// From MDN
return str.replace(escapeRegexpRE, String.raw`\$&`) // $& means the whole matched string
}
function trimWS(str, wsLeft, wsRight) {
// Slightly confusing,
// but _}} will trim the left side of the following string
const leftTrim = wsLeft || wsLeft === false ? wsLeft : 'nl'
const rightTrim = wsRight || wsRight === false ? wsRight : false
if (!rightTrim && !leftTrim) return str
if (leftTrim === 'slurp' && rightTrim === 'slurp') {
return str.trim()
}View on GitHub (pinned to 4841521b5f)
Solutions
- Open the file/line/column named in the error message and fix the unclosed comment, string or tag (add the closing '%>', quote or comment terminator)
- Check for leftover Git merge-conflict markers in the template file
- If you didn't edit templates, reinstall create-quasar (npm i -g create-quasar@latest) to replace corrupted template assets
- Run the failing command again to confirm parsing succeeds
Example fix
// before (template.js asset) <div class="<%= props.name // after <div class="<%= props.name %>"></div>
Defensive patterns
Strategy: try-catch
Validate before calling
const fs = require('fs')
function looksBalanced(tpl) {
return (tpl.match(/<%/g) || []).length === (tpl.match(/%>/g) || []).length
}
// check before processing: if (!looksBalanced(fs.readFileSync(file, 'utf8'))) fix file first Type guard
function isClosedTag(tpl) {
return typeof tpl === 'string' && (tpl.match(/<%/g) || []).length === (tpl.match(/%>/g) || []).length
} Try / catch
try {
const ast = getAST(tplPath)
} catch (err) {
if (err.message.includes('unclosed')) {
console.error(`Malformed template at ${err.message}; restore or fix the template file`)
}
throw err
} Prevention
- Never hand-edit create-quasar templates without re-running the scaffolding command afterwards
- Reject merge conflicts in CI by grepping template folders for '<<<<<<<' markers
- Keep a pristine copy of templates from the published package for diffing
- Use an editor mode that highlights EJS tags so unclosed '%>' is visible
When it happens
Trigger: getAST encounters a template file containing an unterminated tag/comment/string literal — e.g. a template edited by hand where a closing '%>' or quote was dropped, or a line/comment opened at the end of the file.
Common situations: Developers customizing create-quasar's built-in templates (in template/ folders) accidentally break a tag; merge conflicts leaving conflict markers inside a template; editing templates with an editor that mangles quotes; contributing a new template with unbalanced syntax.
Related errors
- cancelScaffolding() expects an options object: { message?, e
- ${assetRelativePath} already exists.
- Could not generate ${assetRelativePath}.
- Could not generate ${relativePath}.
- Please check the source around "<%" and "%>" for invalid usa
AI-assisted analysis of quasarframework/quasar@4841521b5f (2026-08-30).
Data as JSON: /api/errors/413df714fe4fddf8.
Report an issue: GitHub.