toon-format/toon · error · ToonDecodeError
Unexpected bare token line outside root primitive position
Error message
Unexpected bare token line outside root primitive position
What it means
A line that is neither a list item (`- ...`) nor contains an unquoted `key:` colon is a bare token; outside the document's single root-primitive position such lines have no valid meaning. assertNotScalarLine throws this to reject stray scalar lines inside objects/arrays. It is called from decodeDocument and decodeObjectFields.
Source
Thrown at packages/toon/src/decode/decoders.ts:139
}
}
function overIndentedLineError(line: ParsedLine, expectedDepth: Depth): ToonDecodeError {
return new ToonDecodeError(
`Over-indented line: expected depth ${expectedDepth}, but found ${line.depth}`,
{ line: line.lineNumber, source: line.raw },
)
}
// Both modes reject a bare token outside root primitive position, so it must not reach
// the non-strict paths that drop an over-indented line.
function assertNotScalarLine(line: ParsedLine): void {
const isListItem = line.content.startsWith(LIST_ITEM_PREFIX) || line.content === LIST_ITEM_MARKER
if (isListItem || findUnquotedChar(line.content, COLON) !== -1) {
return
}
throw new ToonDecodeError(
'Unexpected bare token line outside root primitive position',
{ line: line.lineNumber, source: line.raw },
)
}
function keylessKeyedError(line: ParsedLine): ToonDecodeError {
return new ToonDecodeError(
'Keyless keyed header is only valid at the document root',
{ line: line.lineNumber, source: line.raw },
)
}
function keylessHeaderError(line: ParsedLine): ToonDecodeError {
return new ToonDecodeError(
'Keyless array header is only valid at the document root or as a list item',
{ line: line.lineNumber, source: line.raw },
)
}View on GitHub (pinned to 604eac266e)
Solutions
- Restore the missing `key: ` prefix on the offending line
- Quote the text so its colon is preserved and it parses as a value of a key
- Remove the stray line if it is leftover prose/debris
- If it was meant to be a list entry, prefix it with `- `
Example fix
// before user: Ada Lovelace // after user: name: Ada Lovelace
Defensive patterns
Strategy: validation
Validate before calling
const bareLines = input.split('\n')
.map((raw, i) => ({ raw: raw.trim(), i: i + 1 }))
.filter(l => l.raw && !l.raw.startsWith('- ') && !/^[^:]+:/.test(l.raw))
if (bareLines.length) throw new Error(`Lines without key: ${bareLines.map(l => l.i).join(',')}`) Type guard
function lineIsKeyedOrListItem(line: string): boolean {
const t = line.trim()
return t.startsWith('- ') || /:/.test(t)
} Try / catch
try {
return decode(input)
} catch (e) {
if (e instanceof ToonDecodeError && e.message.includes('bare token')) {
const ln = e.line ?? 0
throw new Error(`Line ${ln} is missing its key; every non-list line needs 'key: value'`)
}
throw e
} Prevention
- Ensure every nested line has an unquoted `key: ` prefix or `- ` prefix
- Quote strings containing colons carefully; avoid stripping quotes when editing
- Lint generated output for colon-less lines before decoding
When it happens
Trigger: decodeDocument or decodeObjectFields encounters a line whose content has no unquoted colon and no list-item prefix, e.g. a value missing its key, or an unquoted string containing no colon in a nested block.
Common situations: Deleting a key but leaving the value on its own line; multi-line strings split without proper quoting; markdown or prose accidentally pasted into the file; a line where the colon got quoted away or removed.
Related errors
- Top-level document must start with a key-value or array-head
- Indentation depth jump: expected depth ${parentDepth + 1}, b
- Unexpected content after the document root
- Duplicate sibling key "${key}"
- Unexpected indentation inside keyed tabular object
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/9d33f643fdcd5c89.
Report an issue: GitHub.