{"record":{"id":"fac8d52fc3e2a56e","repo":"JuliusBrussee/caveman","slug":"write-report-w","errorCode":null,"errorMessage":"write report: %w","messagePattern":"write report: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/cmd/caveman-engine/main.go","lineNumber":141,"sourceCode":"\tif compressErr != nil {\n\t\tif !bytes.Equal(res.Output, input) || !res.PassedThrough() || res.TokensAfter != res.TokensBefore {\n\t\t\treturn fmt.Errorf(\"unsafe recovery failure result: %w\", compressErr)\n\t\t}\n\t\tcode = \"cave_ccr_unavailable\"\n\t\tif errors.Is(compressErr, ccr.ErrBudgetExceeded) {\n\t\t\tcode = \"cave_ccr_budget_exceeded\"\n\t\t}\n\t}\n\tif _, err := stdout.Write(res.Output); err != nil {\n\t\treturn fmt.Errorf(\"write stdout: %w\", err)\n\t}\n\t// Report stays on stderr so stdout remains clean payload bytes.\n\treport, err := json.Marshal(compressReport{Result: res, Error: code})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"encode report: %w\", err)\n\t}\n\tif _, err := fmt.Fprintln(stderr, string(report)); err != nil {\n\t\treturn fmt.Errorf(\"write report: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc runDetect() {\n\tinput, err := readBoundedInput(os.Stdin, maxStdinBytes)\n\tif err != nil {\n\t\tfatal(\"read stdin: %v\", err)\n\t}\n\t// Detection needs no store.\n\teng := engine.New(nil, nil)\n\tfmt.Println(eng.Detect(input))\n}\n\nfunc runRetrieve(args []string) {\n\tif len(args) < 1 {\n\t\tfatal(\"usage: caveman-engine retrieve <handle> [query]\")\n\t}","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/engine/cmd/caveman-engine/main.go#L123-L159","documentation":"The engine CLI could not write the JSON compress report line to stderr. Like a stdout failure this is a pipe/filesystem condition: stderr is closed, the pipe consumer exited, or the redirect target rejects writes. The payload has already been written to stdout, so only telemetry is lost.","triggerScenarios":"Running with stderr redirected to a full or read-only file, or 2>n where the reader exits early; stderr explicitly closed (e.g. 2>&-).","commonSituations":"CI systems that discard or cap stderr; scripts redirecting stderr to a small tmpfs; daemonized invocation with all descriptors closed.","solutions":["Check where stderr points and that it is writable and has space.","Avoid closing stderr; redirect it to a file with headroom or to /dev/null deliberately.","If you depend on the report, capture stderr to a file rather than a pipe with an early-exiting reader.","Remember stdout already got the payload — a retry is safe and idempotent for pass-through inputs."],"exampleFix":"# before: stderr closed\ncaveman-engine compress < in 2>&-\n\n# after: capture the report\ncaveman-engine compress < in 2>report.json","handlingStrategy":"validation","validationCode":"// Ensure stderr is writable before the run\nif _, err := os.Stderr.Write(nil); err != nil {\n    return fmt.Errorf(\"stderr unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Redirect stderr to a regular file, not a pipe with an early-exiting reader.","Never launch with stderr closed (2>&-).","In CI, give stderr a dedicated file with adequate size allowance."],"tags":["cli","stderr","io","report"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}