{"record":{"id":"0236dbde3499ce29","repo":"toon-format/toon","slug":"over-indented-line-expected-depth-expecteddepth","errorCode":null,"errorMessage":"Over-indented line: expected depth ${expectedDepth}, but found ${line.depth}","messagePattern":"Over-indented line: expected depth (.+?), but found (.+?)","errorType":"exception","errorClass":"ToonDecodeError","httpStatus":null,"severity":"error","filePath":"packages/toon/src/decode/decoders.ts","lineNumber":97,"sourceCode":"    throw new ToonDecodeError(\n      'Top-level document must start with a key-value or array-header line',\n      { line: first.lineNumber, source: first.raw },\n    )\n  }\n\n  const rootSeenKeys = options.strict ? new Set<string>() : undefined\n  yield { type: 'startObject' }\n  yield* decodeKeyValue(first, reader, 0, options, rootSeenKeys)\n\n  while (true) {\n    const line = yield* peekLine(reader)\n    if (!line) {\n      break\n    }\n\n    if (line.depth !== 0) {\n      if (options.strict) {\n        throw overIndentedLineError(line, 0)\n      }\n      assertNotScalarLine(line)\n      yield* readLine(reader)\n      continue\n    }\n\n    yield* readLine(reader)\n    yield* decodeKeyValue(line, reader, 0, options, rootSeenKeys)\n  }\n\n  yield { type: 'endObject' }\n}\n\n// #endregion\n\n// #region Error helpers\n\nfunction assertNoDepthJump(firstNestedLine: ParsedLine, parentDepth: Depth, strict: boolean): void {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/toon-format/toon/blob/604eac266e35166bed6f5b9e3bd586e9c60a9330/packages/toon/src/decode/decoders.ts#L79-L115","documentation":"At the document root, TOON expects every line at depth 0. In strict mode, a line indented deeper than the root level throws overIndentedLineError, reporting the expected depth (0) and the actual depth found. This catches structurally malformed documents early.","triggerScenarios":"Calling decode/decodeStreamSync on input whose first meaningful lines (or any non-empty line before any top-level key) are indented, e.g. a document that starts with a line at depth 2, with strict: true (the default).","commonSituations":"Wrapping TOON output inside YAML/JSON artifacts and decoding the indented block; copy-pasting snippets that carry leading indentation from editors/chat; mixing strict and non-strict workflows.","solutions":["Remove the leading indentation from the lines being decoded","Decode only the intended sub-document, not an indented fragment","Set options.strict = false to tolerate over-indented lines (they are skipped per the non-strict path)","Re-encode the source data to produce properly rooted TOON output"],"exampleFix":"// before (input, strict mode)\nconst text = \"    items: 2\"\nconst doc = decode(text)\n// after\nconst text = \"items: 2\"\nconst doc = decode(text)","handlingStrategy":"validation","validationCode":"function isRootedToon(text: string): boolean {\n  return text.split('\\n').every(line => line.trim() === '' || line[0] !== ' ' && line[0] !== '\\t' || /* allow continuation */ true)\n}","typeGuard":null,"tryCatchPattern":"try {\n  const doc = decode(text)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Over-indented line')) {\n    // dedent the input and retry once\n    const dedented = text.split('\\n').map(l => l.replace(/^\\s+/, '')).join('\\n')\n    return decode(dedented)\n  }\n  throw e\n}","preventionTips":["Strip common leading indentation when extracting TOON snippets from larger files","Keep strict mode on in CI to catch malformed documents early","Store TOON as generated by the encoder, never hand-indented"],"tags":["decoder","indentation","strict-mode","structure"],"backgroundTag":"over-indented-line","analyzedSha":"604eac266e35166bed6f5b9e3bd586e9c60a9330","analyzedAt":"2026-08-31T11:09:25.043Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}