{"record":{"id":"6b79511f9181d975","repo":"toon-format/toon","slug":"unexpected-endobject-event","errorCode":null,"errorMessage":"Unexpected endObject event","messagePattern":"Unexpected endObject event","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/toon/src/decode/event-builder.ts","lineNumber":79,"sourceCode":"            throw new Error('Object startObject event without preceding key')\n          }\n\n          setOwnProperty(parent.obj, parent.currentKey, obj)\n          parent.currentKey = undefined\n        }\n        else if (parent.type === 'array') {\n          parent.arr.push(obj)\n        }\n\n        stack.push({ type: 'object', obj })\n      }\n\n      break\n    }\n\n    case 'endObject': {\n      if (stack.length === 0) {\n        throw new Error('Unexpected endObject event')\n      }\n\n      const context = stack.pop()!\n      if (context.type !== 'object') {\n        throw new Error('Mismatched endObject event')\n      }\n\n      if (stack.length === 0) {\n        state.root = context.obj\n      }\n\n      break\n    }\n\n    case 'startArray': {\n      const arr: JsonValue[] = []\n\n      if (stack.length === 0) {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/toon-format/toon/blob/604eac266e35166bed6f5b9e3bd586e9c60a9330/packages/toon/src/decode/event-builder.ts#L61-L97","documentation":"applyEvent received an endObject event while the nesting stack is empty — there is no open object to close, so the event stream is unbalanced.","triggerScenarios":"A stream with more endObject events than startObject events, or endObject as the first event.","commonSituations":"Truncated or corrupted event streams; off-by-one bugs in custom event producers.","solutions":["Balance each endObject with a corresponding startObject","Fix the emitter that drops startObject or emits extra endObject events","Pre-validate start/end balance before building"],"exampleFix":"// before\n[{type:'endObject'}] // unbalanced\n// after\n[{type:'startObject'},{type:'endObject'}]","handlingStrategy":"validation","validationCode":"function hasNoExtraEndObject(events) {\n  let depth = 0\n  for (const ev of events) {\n    if (ev.type === 'startObject') depth++\n    if (ev.type === 'endObject') { depth--; if (depth < 0) return false }\n  }\n  return depth === 0\n}","typeGuard":null,"tryCatchPattern":"try {\n  const value = buildValueFromEvents(events)\n} catch (e) {\n  if (e.message === 'Unexpected endObject event') {\n    throw new Error('Unbalanced event stream: endObject without startObject')\n  }\n  throw e\n}","preventionTips":["Track nesting depth in the emitter and assert depth > 0 before emitting endObject","Balance-check streams in tests before feeding the builder","Never hand-truncate event streams; regenerate from source data"],"tags":["event-stream","decoder","toon"],"backgroundTag":"malformed-event-stream","analyzedSha":"604eac266e35166bed6f5b9e3bd586e9c60a9330","analyzedAt":"2026-08-31T11:09:25.043Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}