{"record":{"id":"e92f6408813b2397","repo":"JuliusBrussee/caveman","slug":"cachebench-no-observation-records","errorCode":null,"errorMessage":"cachebench: no observation records","messagePattern":"cachebench: no observation records","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cacheengine/cachebench/observed.go","lineNumber":142,"sourceCode":"\t\tvar trailing any\n\t\tif err := decoder.Decode(&trailing); err != io.EOF {\n\t\t\treturn nil, fmt.Errorf(\"cachebench: observation line %d: trailing JSON\", line)\n\t\t}\n\t\tif record.Schema != ObservationSchema {\n\t\t\treturn nil, fmt.Errorf(\"cachebench: observation line %d: schema %q\", line, record.Schema)\n\t\t}\n\t\tif strings.TrimSpace(record.RequestID) == \"\" || seen[record.RequestID] {\n\t\t\treturn nil, fmt.Errorf(\"cachebench: observation line %d: empty or duplicate request_id\", line)\n\t\t}\n\t\tseen[record.RequestID] = true\n\t\trecord.Usage = append(json.RawMessage(nil), record.Usage...)\n\t\trecords = append(records, record)\n\t}\n\tif err := scanner.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"cachebench: read observations: %w\", err)\n\t}\n\tif len(records) == 0 {\n\t\treturn nil, errors.New(\"cachebench: no observation records\")\n\t}\n\tif err := validateObservationRecords(records); err != nil {\n\t\treturn nil, err\n\t}\n\treturn records, nil\n}\n\n// EvaluateObserved evaluates supplied observations without completeness claim.\nfunc EvaluateObserved(records []ObservationRecord, target Target) (Report, error) {\n\tif err := validateTarget(target); err != nil {\n\t\treturn Report{}, err\n\t}\n\tif len(records) == 0 {\n\t\treturn Report{}, errors.New(\"cachebench: no observation records\")\n\t}\n\tif err := validateObservationRecords(records); err != nil {\n\t\treturn Report{}, err\n\t}","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/cachebench/observed.go#L124-L160","documentation":"ReadObservationJSONLWithLimits parsed zero records from the input stream and treats that as an error: an observations file with no usable lines (only whitespace or empty) cannot support any evaluation. The check runs after the scan loop and scanner error check.","triggerScenarios":"Feeding an empty file, a file of blank lines, or a reader already consumed to EOF to ReadObservationJSONL. All lines were skipped as blank, so records stays empty and the function errors instead of returning an empty slice.","commonSituations":"Observation export produced an empty file (job crashed before writing); reading a file whose content was already consumed by an earlier scanner; wrong path resolving to an empty placeholder file.","solutions":["Verify the observation file is non-empty and starts with a JSON object line before parsing","Check file size / first bytes after export and treat 0 bytes as an export failure","If empty input is legitimate in your flow, catch this specific error and handle it as 'nothing to evaluate'"],"exampleFix":"// before\nrecs, err := ReadObservationJSONL(emptyFile) // error: no observation records\n\n// after\nif fi, _ := f.Stat(); fi.Size() == 0 {\n    return fmt.Errorf(\"observation export %s is empty; rerun exporter\", fi.Name())\n}\nrecs, err := ReadObservationJSONL(f)","handlingStrategy":"validation","validationCode":"fi, err := os.Stat(path)\nif err != nil { return err }\nif fi.Size() == 0 {\n    return fmt.Errorf(\"observation file %s is empty\", path)\n}\nrecords, err := cachebench.ReadObservationJSONL(f)","typeGuard":null,"tryCatchPattern":"records, err := cachebench.ReadObservationJSONL(f)\nif err != nil {\n    if err.Error() == \"cachebench: no observation records\" {\n        // treat as export failure: rerun exporter or flag pipeline\n    }\n    return err\n}","preventionTips":["Check observation file size right after export; zero bytes means the exporter failed","Don't share one io.Reader across parsers — a consumed reader yields zero records","Validate the first line parses as a JSON object before committing to full read"],"tags":["go","observations","jsonl","empty-input"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}