toon-format/toon · error · ToonDecodeError
Expected list item to start with "${LIST_ITEM_PREFIX}"
Error message
Expected list item to start with "${LIST_ITEM_PREFIX}" What it means
Every list entry line must begin with the `- ` list-item prefix. decodeListItem throws this ToonDecodeError when the line it reads at the list-item depth does not start with `- `. This keeps list syntax unambiguous.
Source
Thrown at packages/toon/src/decode/decoders.ts:548
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 },
)
}
if (!trimSpaces(afterHyphen)) {
yield { type: 'startObject' }
yield { type: 'endObject' }
return
}
if (trimSpaces(afterHyphen) === '[]') {
yield { type: 'startArray', length: 0 }
yield { type: 'endArray' }
return
}
const itemLine: ParsedLine = { ...line, content: afterHyphen }View on GitHub (pinned to 604eac266e)
Solutions
- Prefix the line with `- `
- Fix the indentation so non-list lines sit at the correct depth
- Convert the structure to a tabular array header if rows are keyed
- Use `[N]{fields}:` syntax instead of a bare list for keyed rows
Example fix
// before tags[2]: a b // after tags[2]: - a - b
Defensive patterns
Strategy: validation
Validate before calling
function allListLinesPrefixed(text: string): boolean {
const lines = text.split('\n').filter(l => l.trim())
const listIdx = lines.findIndex(l => /^ *\[\d+\]\s*:/.test(l))
if (listIdx === -1) return true
return lines.slice(listIdx + 1).every(l => !l.trim() || /^ *(- |\[\d+\])/.test(l) === false ? false : true || true) // simplified: verify below
}
// practical check: any line under a bare list header must match /^\s*- / Type guard
function isListItemLine(line: string): boolean {
return line.trimStart().startsWith('- ')
} Try / catch
try {
return decode(input)
} catch (e) {
if (e instanceof ToonDecodeError && e.message.includes('to start with')) {
throw new Error(`Line ${e.line}: list entries must begin with '- '`)
}
throw e
} Prevention
- Always prefix list entries with `- ` (hyphen + space)
- Use the encoder for lists instead of hand-writing them
- Lint for lines inside list blocks lacking the prefix
When it happens
Trigger: decodeListArray -> decodeListItem reads a line at the item depth whose content does not start with LIST_ITEM_PREFIX (`- `), e.g. a row like `a, b` or `name: x` directly under a list header.
Common situations: Forgetting the `- ` when typing list entries by hand; converting CSV lines into a list without the prefix; indentation confusion placing an object field at list-item depth.
Related errors
- Expected list item
- result.reason
- result.strictError
- Top-level document must start with a key-value or array-head
- Indentation depth jump: expected depth ${parentDepth + 1}, b
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/5a73360efac22d3f.
Report an issue: GitHub.