{"record":{"id":"40134ebf075effe9","repo":"JuliusBrussee/caveman","slug":"not-valid-toon","errorCode":null,"errorMessage":"not valid TOON","messagePattern":"not valid TOON","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"info","filePath":"engine/cmd/caveman-engine/main.go","lineNumber":623,"sourceCode":"\n// toonEncodeBytes converts JSON to the lossless TOON subset. It fails closed:\n// any input that is not valid JSON, or whose shape is outside the proven\n// round-trip subset (deeply nested / non-uniform), returns an error rather than a\n// lossy approximation — so the caller keeps JSON instead of trusting bad TOON.\nfunc toonEncodeBytes(input []byte) ([]byte, error) {\n\tout, ok := compressors.NewTOON().Compress(input)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"not losslessly TOON-encodable (invalid JSON, or nested/non-uniform shape); keep JSON\")\n\t}\n\treturn out, nil\n}\n\n// toonDecodeBytes converts TOON back to compact JSON. Malformed TOON fails closed\n// with an error; it never emits partial or guessed JSON.\nfunc toonDecodeBytes(input []byte) ([]byte, error) {\n\tv, ok := compressors.DecodeTOON(input)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"not valid TOON\")\n\t}\n\tout, err := json.Marshal(v)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn out, nil\n}\n\nfunc runEvals(args []string) {\n\tif len(args) < 1 || args[0] != \"run\" {\n\t\tfatal(\"usage: caveman-engine evals run [--fixtures DIR]\")\n\t}\n\tfixtureDir := \"\"\n\tif len(args) == 3 && args[1] == \"--fixtures\" && args[2] != \"\" {\n\t\tfixtureDir = args[2]\n\t} else if len(args) != 1 {\n\t\tfatal(\"usage: caveman-engine evals run [--fixtures DIR]\")\n\t}","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/engine/cmd/caveman-engine/main.go#L605-L641","documentation":"toonDecodeBytes was given bytes that DecodeTOON cannot parse as TOON. Decoding fails closed with an error — it never emits partial or guessed JSON — so malformed or truncated TOON input is surfaced rather than silently corrupted.","triggerScenarios":"Calling toonDecodeBytes on data that is not TOON-encoded (e.g. still plain JSON because encoding fell back, or hand-mangled/truncated TOON).","commonSituations":"Round-trip asymmetry where encode fell back to JSON but the consumer assumes TOON; truncated payload from a transport; version skew between TOON writer and reader.","solutions":["Verify the producer actually emitted TOON — remember encode intentionally falls back to JSON on unsupported shapes, so detect format first.","Check the payload for truncation (compare lengths/hashes end to end).","Keep producer and consumer on the same engine/compressors version.","On error, surface it upstream rather than retrying blindly — the bytes are wrong, not the timing."],"exampleFix":"// before\njson_out, err := toonDecodeBytes(payload)\n\n// after: sniff format, decode conditionally\nvar json_out []byte\nif compressors.IsTOON(payload) { json_out, err = toonDecodeBytes(payload) } else { json_out = payload }","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isTOON(b []byte) bool {\n    _, ok := compressors.DecodeTOON(b)\n    return ok\n}","tryCatchPattern":"if out, err := toonDecodeBytes(payload); err != nil {\n    // payload is not TOON: either plain JSON or corrupt; handle explicitly\n    return handleNonTOON(payload)\n} else {\n    use(out)\n}","preventionTips":["Carry a format marker (sidecar flag or magic) alongside the payload.","Remember encode may fall back to JSON, so always sniff before decoding.","Verify payload integrity (length/hash) across transports."],"tags":["toon","decode","fail-closed","round-trip"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}