{"record":{"id":"ed225b06eab0e08c","repo":"toon-format/toon","slug":"expected-entry-row-inside-keyed-tabular-object","errorCode":null,"errorMessage":"Expected entry row inside keyed tabular object","messagePattern":"Expected entry row inside keyed tabular object","errorType":"exception","errorClass":"ToonDecodeError","httpStatus":null,"severity":"error","filePath":"packages/toon/src/decode/decoders.ts","lineNumber":373,"sourceCode":"    const line = yield* peekLine(reader)\n    if (!line || line.depth <= baseDepth) {\n      break\n    }\n\n    if (line.depth > entryDepth) {\n      if (options.strict) {\n        throw new ToonDecodeError(\n          'Unexpected indentation inside keyed tabular object',\n          { line: line.lineNumber, source: line.raw },\n        )\n      }\n      yield* readLine(reader)\n      continue\n    }\n\n    if (findUnquotedChar(line.content, COLON) === -1) {\n      if (options.strict) {\n        throw new ToonDecodeError(\n          'Expected entry row inside keyed tabular object',\n          { line: line.lineNumber, source: line.raw },\n        )\n      }\n      yield* readLine(reader)\n      continue\n    }\n\n    yield* readLine(reader)\n    if (startLine === undefined) {\n      startLine = line.lineNumber\n    }\n    endLine = line.lineNumber\n    lastEntryLine = line\n\n    const { key, end } = withLine(line, () => parseKeyToken(line.content, 0))\n    assertNoDuplicateKey(key, line, seenEntryKeys)\n    yield { type: 'key', key }","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/toon-format/toon/blob/604eac266e35166bed6f5b9e3bd586e9c60a9330/packages/toon/src/decode/decoders.ts#L355-L391","documentation":"Every line inside a keyed tabular object must be an entry row of the form `key: value`; a line without an unquoted colon cannot be a row. In strict mode decodeKeyedObject throws instead of skipping the malformed line (non-strict reads and discards it).","triggerScenarios":"decodeKeyedObject, while consuming rows under a keyed tabular array header, finds a line at the entry depth whose content contains no unquoted `:` and options.strict is true.","commonSituations":"A row missing its key/value separator; prose or comment text accidentally inside the table; a value split across lines leaving a colon-less continuation line.","solutions":["Add the missing `key: ` to the offending row","Join the split line back to its key on the previous line","Remove the stray non-row line","Decode with strict:false so the line is skipped"],"exampleFix":"// before\nusers[2]{name}:\n  Ada Lovelace\n  name: Grace\n\n// after\nusers[2]{name}:\n  name: Ada\n  name: Grace","handlingStrategy":"validation","validationCode":"function tabularRowsAllKeyed(text: string): boolean {\n  const lines = text.split('\\n')\n  const tableIdx = lines.findIndex(l => /^ *\\[\\d+\\]\\{.*\\}:/.test(l))\n  if (tableIdx === -1) return true\n  for (let i = tableIdx + 1; i < lines.length; i++) {\n    const l = lines[i]\n    if (!l.trim()) break\n    if (!/^ *[^:]+:/.test(l)) return false\n  }\n  return true\n}","typeGuard":null,"tryCatchPattern":"try {\n  return decode(input, { strict: true })\n} catch (e) {\n  if (e instanceof ToonDecodeError && e.message.includes('entry row')) {\n    return decode(input, { strict: false }) // malformed rows skipped\n  }\n  throw e\n}","preventionTips":["Every row under a keyed tabular header must be `key: value`","Join continuation lines so values never wrap onto a bare line","Validate generated tables with the encoder round-trip"],"tags":["toon","decoder","strict-mode","tabular","malformed-row"],"backgroundTag":"bare-token-line","analyzedSha":"604eac266e35166bed6f5b9e3bd586e9c60a9330","analyzedAt":"2026-08-31T11:09:25.043Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}