toon-format/toon · error · SyntaxError
Unterminated string: missing closing quote
Error message
Unterminated string: missing closing quote
What it means
A primitive token in the TOON input started with a double quote, indicating a quoted string, but findClosingQuote could not locate an unescaped closing quote before end-of-token. The parser throws SyntaxError rather than treating the rest of the line as string content, since the token boundaries are ambiguous.
Source
Thrown at packages/toon/src/decode/parser.ts:475
return null
}
if (isNumericLiteral(trimmedToken)) {
const parsedNumber = Number.parseFloat(trimmedToken)
return Object.is(parsedNumber, -0) ? 0 : parsedNumber
}
return trimmedToken
}
export function parseStringLiteral(token: string): string {
const trimmedToken = trimSpaces(token)
if (trimmedToken.startsWith(DOUBLE_QUOTE)) {
const closingQuoteIndex = findClosingQuote(trimmedToken, 0)
if (closingQuoteIndex === -1) {
throw new SyntaxError('Unterminated string: missing closing quote')
}
if (closingQuoteIndex !== trimmedToken.length - 1) {
throw new SyntaxError('Unexpected characters after closing quote')
}
const content = trimmedToken.slice(1, closingQuoteIndex)
return unescapeString(content)
}
return trimmedToken
}
export function parseUnquotedKey(content: string, start: number): { key: string, end: number } {
// A raw scan would cut `a "b:c" d: 1` at the quoted colon and split the key in two.
const colonIndex = findUnquotedChar(content, COLON, start)
if (colonIndex === -1) {View on GitHub (pinned to 604eac266e)
Solutions
- Add the missing closing quote to the string token, e.g. `name: "hello"`
- Check for unescaped inner quotes — escape them as `\"` so the parser doesn't end the string early
- Avoid manual quoting: emit values via toon.encode which quotes/escapes correctly
- Check the file wasn't truncated mid-line (inspect the end of the file/line)
Example fix
// before greeting: "hello // after greeting: "hello"
Defensive patterns
Strategy: try-catch
Validate before calling
function linesHaveClosedQuotes(text) {
return text.split('\n').every(line => {
let n = 0, esc = false
for (const ch of line) {
if (esc) { esc = false; continue }
if (ch === '\\') { esc = true; continue }
if (ch === '"') n++
}
return n % 2 === 0
})
} Try / catch
try {
const value = toon.decode(text)
} catch (err) {
if (err instanceof SyntaxError && err.message === 'Unterminated string: missing closing quote') {
// point at the offending line; fix quoting before retry
} else throw err
} Prevention
- Always close quoted strings on the same line
- Escape inner quotes as \" instead of relying on raw quotes
- Let toon.encode handle quoting of values containing special characters
- Check files for truncation when decode fails on the last line
When it happens
Trigger: Decoding TOON text containing an opening `"` with no closing `"` on the same token/line — e.g. `name: "hello` or an array row cell `"unterminated,x`. Reached via parseStringLiteral from parsePrimitiveToken, parseArrayHeaderLine, or parseFieldEntries.
Common situations: Hand-written TOON where the closing quote was forgotten; text containing characters that were escaped incorrectly so an escaped quote `\"` accidentally consumed the real closing quote; files truncated mid-line; content pasted from sources that strip trailing quotes.
Related errors
- Unexpected characters after closing quote
- Expected list item to start with "${LIST_ITEM_PREFIX}"
- result.reason
- result.strictError
- Invalid array length: "${seg}" (expected non-negative intege
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/66a4c1207c54628a.
Report an issue: GitHub.