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.

Solutions

  1. Emit endObject to close startObject, endArray to close startArray
  2. Fix nesting tracking in the event producer
  3. 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

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


AI-assisted analysis of toon-format/toon@604eac266e (2026-08-31). Data as JSON: /api/errors/32583259db0f6450. Report an issue: GitHub.

Appendix: 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)