toon-format/toon · error · SyntaxError
result.reason
Error message
result.reason
What it means
When resolving an array header that is syntactically recognizable but invalid, strict mode surfaces the header's specific reason (result.reason) as a SyntaxError, while non-strict mode returns undefined so the line is handled as ordinary content. The message text is whatever the header parser reported.
Source
Thrown at packages/toon/src/decode/decoders.ts:667
// #endregion
// #region Shared decoder helpers
// Keeps the detection/parse split free of error decisions. The bare
// SyntaxError is deliberate: the caller's `withLine` wrapper enriches it into a
// `ToonDecodeError` with a `cause`, matching the direct-throw path.
function resolveArrayHeader(
result: ArrayHeaderParseResult,
strict: boolean,
): { header: ArrayHeaderInfo, inlineValues?: string } | undefined {
if (result.kind === 'notHeader') {
return undefined
}
if (result.kind === 'invalid') {
if (strict) {
throw new SyntaxError(result.reason)
}
return undefined
}
// A valid header may still carry a strict-only violation that non-strict resolves via LWW.
if (strict && result.strictError !== undefined) {
throw new SyntaxError(result.strictError)
}
return { header: result.header, inlineValues: result.inlineValues }
}
function* yieldObjectFromFields(
fields: readonly FieldNode[],
primitives: readonly JsonPrimitive[],
): Generator<JsonStreamEvent> {
let cellIndex = 0
View on GitHub (pinned to 604eac266e)
Solutions
- Fix the array header to valid form `[N]{fields}:` with a non-negative integer length
- Validate length matches the actual item count
- Decode with strict:false so invalid headers fall back to normal content parsing
- Check the generator emitting the header for template bugs
Example fix
// before items[abc]: - a // after items[1]: - a
Defensive patterns
Strategy: try-catch
Validate before calling
function arrayHeadersLookValid(text: string): string[] {
const bad: string[] = []
for (const l of text.split('\n')) {
const m = l.match(/^ *\[([^\]]*)\]/)
if (m && !/^\d+$/.test(m[1])) bad.push(l.trim())
}
return bad
} Type guard
function isValidArrayHeader(line: string): boolean {
return /^\s*\[\d+\](\{[^}]*\})?\s*:/.test(line)
} Try / catch
try {
return decode(input, { strict: true })
} catch (e) {
if (e instanceof SyntaxError) {
// e.message is the header parser's result.reason
return decode(input, { strict: false }) // invalid header parsed as regular content
}
throw e
} Prevention
- Emit array headers as `[<nonNegativeInt>]{fields}:` via the encoder
- Validate header lengths equal the actual item count
- Catch SyntaxError separately from ToonDecodeError since strict header failures throw SyntaxError
When it happens
Trigger: resolveArrayHeader (via headerInfo/arrayHeader, called during array decoding) gets result.kind === 'invalid' with strict:true — e.g. `[abc]:` (non-numeric length) or a malformed field-list in `{...}`.
Common situations: Hand-edited array headers with a wrong or missing length; typos like `[2,]:` or `[]:`; generated headers corrupted by template errors; mismatched braces in the field list.
Related errors
- result.strictError
- Top-level document must start with a key-value or array-head
- Indentation depth jump: expected depth ${parentDepth + 1}, b
- Unexpected bare token line outside root primitive position
- Unexpected content after the document root
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/12c9a1056e15cf31.
Report an issue: GitHub.