toon-format/toon · error · ToonDecodeError
Indentation depth jump: expected depth ${parentDepth + 1}, b
Error message
Indentation depth jump: expected depth ${parentDepth + 1}, but found ${firstNestedLine.depth} What it means
In strict mode, nested content may only indent exactly one level deeper than its parent. assertNoDepthJump throws when the first nested line under a key skips levels (e.g. parent at depth 0, child at depth 2), which would be ambiguous indentation in TOON. Non-strict mode tolerates the jump.
Source
Thrown at packages/toon/src/decode/decoders.ts:117
assertNotScalarLine(line)
yield* readLine(reader)
continue
}
yield* readLine(reader)
yield* decodeKeyValue(line, reader, 0, options, rootSeenKeys)
}
yield { type: 'endObject' }
}
// #endregion
// #region Error helpers
function assertNoDepthJump(firstNestedLine: ParsedLine, parentDepth: Depth, strict: boolean): void {
if (strict && firstNestedLine.depth > parentDepth + 1) {
throw new ToonDecodeError(
`Indentation depth jump: expected depth ${parentDepth + 1}, but found ${firstNestedLine.depth}`,
{ line: firstNestedLine.lineNumber, source: firstNestedLine.raw },
)
}
}
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) {View on GitHub (pinned to 604eac266e)
Solutions
- Re-indent the nested block so each level steps by exactly one depth unit
- Decode with strict:false if lenient parsing is acceptable
- Normalize indentation with a formatter/linter before decoding
- Replace tabs with a consistent space count
Example fix
// before (depth jump 0 -> 2)
user:
name: Ada
// after
user:
name: Ada Defensive patterns
Strategy: validation
Validate before calling
function hasUniformIndentStep(text: string, maxStep = 1): boolean {
const depths = text.split('\n')
.filter(l => l.trim())
.map(l => Math.floor((l.match(/^ */) ?? [''])[0].length / 2))
return depths.every((d, i) => i === 0 || d - depths[i - 1] <= maxStep)
} Try / catch
try {
return decode(input, { strict: true })
} catch (e) {
if (e instanceof ToonDecodeError && e.message.includes('Indentation depth jump')) {
return decode(normalizeIndentation(input), { strict: true })
}
throw e
} Prevention
- Use a consistent 2-space (one-depth) indent step everywhere
- Expand tabs to spaces before decoding
- Run a TOON formatter over hand-edited files
- Consider strict:false when ingesting third-party files
When it happens
Trigger: decodeKeyValue encountering a nested block whose first line's depth exceeds parentDepth+1 while options.strict is true — typically input indented with inconsistent step sizes or mixed tab/space expansion.
Common situations: Editing TOON by hand and adding an extra indent level; converting YAML with 4-space indents into TOON where only 2-space steps are expected after normalization; copy-paste that re-indents a block.
Related errors
- Unexpected indentation inside keyed tabular object
- Top-level document must start with a key-value or array-head
- Unexpected bare token line outside root primitive position
- Unexpected content after the document root
- Duplicate sibling key "${key}"
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/317451b3030c1e66.
Report an issue: GitHub.