toon-format/toon · error · Error
Mismatched endArray event
Error message
Mismatched endArray event
What it means
applyEvent popped a context on endArray but the open context was not an array (e.g. an object). Start and end kinds must match.
Source
Thrown at packages/toon/src/decode/event-builder.ts:126
}
else if (parent.type === 'array') {
parent.arr.push(arr)
}
stack.push({ type: 'array', arr })
}
break
}
case 'endArray': {
if (stack.length === 0) {
throw new Error('Unexpected endArray event')
}
const context = stack.pop()!
if (context.type !== 'array') {
throw new Error('Mismatched endArray event')
}
if (stack.length === 0) {
state.root = context.arr
}
break
}
case 'key': {
if (stack.length === 0) {
throw new Error('Key event outside of object context')
}
const parent = stack[stack.length - 1]!
if (parent.type !== 'object') {
throw new Error('Key event outside of object context')
}View on GitHub (pinned to 604eac266e)
Solutions
- Emit endObject to close startObject, endArray to close startArray
- Fix nesting tracking in the event producer
- Validate matched start/end kinds before consuming
Example fix
// before
[{type:'startObject'},{type:'endArray'}] // mismatched
// after
[{type:'startObject'},{type:'endObject'}] Defensive patterns
Strategy: validation
Validate before calling
function endArrayKindsMatch(events) {
const stack = []
for (const ev of events) {
if (ev.type === 'startObject') stack.push('object')
else if (ev.type === 'startArray') stack.push('array')
else if (ev.type === 'endObject') { if (stack.pop() !== 'object') return false }
else if (ev.type === 'endArray') { if (stack.pop() !== 'array') return false }
}
return stack.length === 0
} Try / catch
try {
const value = buildValueFromEvents(events)
} catch (e) {
if (e.message === 'Mismatched endArray event') {
throw new Error('Crossed nesting: endArray closed a non-array context')
}
throw e
} Prevention
- Close containers in strict LIFO order with the matching end kind
- Unit-test deeply nested object/array mixes through your emitter
- Derive end-event emission from the same stack used at start
When it happens
Trigger: A stream where startObject is closed by endArray, passed to buildValueFromEvents/Async.
Common situations: Custom emitters swapping end event names; state-tracking bugs in streaming parsers.
Related errors
- Object startObject event without preceding key
- Unexpected endObject event
- Mismatched endObject event
- Array startArray event without preceding key
- Unexpected endArray event
AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31).
Data as JSON: /api/errors/32583259db0f6450.
Report an issue: GitHub.