JuliusBrussee/caveman · error
object not closed
Error message
object not closed
What it means
After consuming an object's fields, readJSONTOONValue reads one more token and requires it to be the '}' delimiter; anything else raises "object not closed". This enforces well-formed JSON objects so the TOON conversion is lossless and never guesses at boundaries.
Solutions
- Validate the input JSON with `jq empty input.json` before running the TOON verb.
- Ensure the input stream is complete (check the producer didn't truncate the file/pipe).
- Strip comments/trailing commas — feed strict RFC 8259 JSON only.
- If you changed the parser, verify token consumption per branch matches the standard decoder's contract.
Example fix
// before: truncated
echo '{"a": [1,2' | caveman-engine toon
// after
echo '{"a": [1,2]}' | caveman-engine toon Defensive patterns
Strategy: validation
Validate before calling
// strict pre-check with the stdlib
var probe any
if err := json.Unmarshal(input, &probe); err != nil { return err } // catches truncation/mismatched braces Try / catch
v, err := parseJSONTOON(input)
if err != nil && strings.Contains(err.Error(), "object not closed") {
return fmt.Errorf("truncated or malformed JSON object: %w", err)
} Prevention
- Run `jq empty` on input before the TOON verb
- Ensure producers finish writing before the engine reads (flush/close)
- Feed strict RFC 8259 JSON — no comments or trailing commas
When it happens
Trigger: In the object branch of readJSONTOONValue, the closing dec.Token() returns a non-Delim token or a Delim other than '}' — e.g. truncated JSON, a stray ']' instead of '}', or a tokenizer that stopped early.
Common situations: Truncated JSON from a cut-off pipe or partial file; mismatched braces from string-assembled JSON; feeding JSON5/JSONC (comments, trailing commas) that the strict parser mishandles; a bug in a rewritten parser loop.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- not losslessly TOON-encodable (invalid JSON, or…
- array not closed
- duplicate object key
- eval evidence line is not valid JSON
- not losslessly TOON-encodable (invalid JSON, or…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/65044ea2f5ba712b.
Report an issue: GitHub.
Appendix: source
Thrown at engine/compressors/toon_encode.go:158
if !ok {
return toonValue{}, fmt.Errorf("object key is %T", keyTok)
}
if _, duplicate := seen[key]; duplicate {
return toonValue{}, fmt.Errorf("duplicate object key %q", key)
}
seen[key] = struct{}{}
val, err := readJSONTOONValue(dec)
if err != nil {
return toonValue{}, err
}
fields = append(fields, toonField{name: key, value: val})
}
end, err := dec.Token()
if err != nil {
return toonValue{}, err
}
if d, ok := end.(json.Delim); !ok || d != '}' {
return toonValue{}, fmt.Errorf("object not closed")
}
return toonValue{kind: toonObject, obj: fields}, nil
case '[':
var arr []toonValue
for dec.More() {
val, err := readJSONTOONValue(dec)
if err != nil {
return toonValue{}, err
}
arr = append(arr, val)
}
end, err := dec.Token()
if err != nil {
return toonValue{}, err
}
if d, ok := end.(json.Delim); !ok || d != ']' {
return toonValue{}, fmt.Errorf("array not closed")
}View on GitHub (pinned to 3ee70a1026)