toon-format/toon · error · ReferenceError
Expected list item
Error message
Expected list item
What it means
decodeListItem is asked to consume one list item but the line reader returned no line (end of input), so the structure promises a `- ` item that is missing. This is thrown as a plain ReferenceError, indicating truncated input rather than a styled ToonDecodeError.
Source
Thrown at packages/toon/src/decode/decoders.ts:534
if (options.strict && startLine !== undefined && endLine !== undefined) {
validateNoBlankLinesInRange(startLine, endLine, reader.scanState.blankLines, options.strict, 'list-form array')
}
if (options.strict) {
const nextLine = yield* peekLine(reader)
validateNoExtraListItems(nextLine, itemDepth, header.length)
}
}
function* decodeListItem(
reader: LineReader,
baseDepth: Depth,
options: DecoderContext,
): LineRule {
const line = yield* readLine(reader)
if (!line) {
throw new ReferenceError('Expected list item')
}
let afterHyphen: string
if (line.content === LIST_ITEM_MARKER) {
yield { type: 'startObject' }
yield { type: 'endObject' }
return
}
else if (line.content.startsWith(LIST_ITEM_PREFIX)) {
afterHyphen = line.content.slice(LIST_ITEM_PREFIX.length)
}
else {
throw new ToonDecodeError(
`Expected list item to start with "${LIST_ITEM_PREFIX}"`,
{ line: line.lineNumber, source: line.raw },
)
}View on GitHub (pinned to 604eac266e)
Solutions
- Add the missing `- ` list item line
- Correct the count in the array header (e.g. `[3]:` -> `[2]:`)
- Regenerate the document from the source data
- Verify the file was not truncated in transit
Example fix
// before tags[2]: - a // after tags[2]: - a - b
Defensive patterns
Strategy: try-catch
Validate before calling
function listItemsMatchCount(text: string): boolean {
const m = text.match(/^ *\[(\d+)\]:/m)
if (!m) return true
const want = Number(m[1])
const got = text.split('\n').filter(l => /^ *- /.test(l)).length
return got >= want
} Type guard
function hasEnoughListItems(text: string): boolean {
const header = text.match(/\[(\d+)\]/)
if (!header) return true
const count = (text.match(/^\s*- /gm) ?? []).length
return count >= Number(header[1])
} Try / catch
try {
return decode(input)
} catch (e) {
if (e instanceof ReferenceError && e.message === 'Expected list item') {
throw new Error('Input truncated: declared list length exceeds available items')
}
throw e
} Prevention
- Keep the array-header count in sync with the item lines
- Regenerate documents from data instead of hand-editing lengths
- Check files for truncation after transfer/merge
When it happens
Trigger: decodeListArray iterating N declared items calls decodeListItem, but the stream ends before the expected `- ` line — e.g. the declared array length exceeds the number of list-item lines present.
Common situations: A truncated or manually edited file where the `[3]:` header still claims 3 items but only 2 remain; a generator bug writing fewer items than declared; line-loss from a bad merge.
Related errors
- Expected list item to start with "${LIST_ITEM_PREFIX}"
- 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/7c61fac4659ee5be.
Report an issue: GitHub.