{"record":{"id":"79c99c5d941cefe7","repo":"JuliusBrussee/caveman","slug":"cachebench-trace-request-q-has-invalid-prefix","errorCode":null,"errorMessage":"cachebench: trace request %q has invalid prefix","messagePattern":"cachebench: trace request %q has invalid prefix","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cacheengine/cachebench/observed.go","lineNumber":52,"sourceCode":"\tif err := validateObservationRecords(records); err != nil {\n\t\treturn Report{}, err\n\t}\n\tif len(records) != len(trace) {\n\t\treturn Report{}, fmt.Errorf(\"cachebench: observation population %d does not match trace population %d\", len(records), len(trace))\n\t}\n\tbyID := make(map[string]TraceRecord, len(trace))\n\tfor index, request := range trace {\n\t\tif request.Schema != TraceSchema && request.Schema != TraceSchemaV2 || strings.TrimSpace(request.RequestID) == \"\" {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: trace request %d has invalid schema or request_id\", index)\n\t\t}\n\t\tif _, exists := byID[request.RequestID]; exists {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: duplicate trace request %q\", request.RequestID)\n\t\t}\n\t\tif strings.TrimSpace(request.Provider) == \"\" || strings.TrimSpace(request.Epoch) == \"\" || !validUniqueJSONObject(request.Body) || request.BodySHA256 == \"\" || request.BodySHA256 != bodyDigest(request.Body) {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: trace request %q has invalid identity, body, or digest\", request.RequestID)\n\t\t}\n\t\tif request.StableSegmentCount < 0 || request.StableSegmentCount > len(request.Prefix) || !validPrefix(request.Prefix) {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: trace request %q has invalid prefix\", request.RequestID)\n\t\t}\n\t\tbyID[request.RequestID] = request\n\t}\n\tfor _, record := range records {\n\t\trequest, exists := byID[record.RequestID]\n\t\tif !exists {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: observation request %q absent from trace\", record.RequestID)\n\t\t}\n\t\tif record.Provider != request.Provider || record.Epoch != request.Epoch {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: observation request %q provider/epoch mismatch\", record.RequestID)\n\t\t}\n\t\tif record.RequestBodySHA256 == \"\" || record.RequestBodySHA256 != request.BodySHA256 {\n\t\t\treturn Report{}, fmt.Errorf(\"cachebench: observation request %q body digest mismatch\", record.RequestID)\n\t\t}\n\t}\n\treport, err := EvaluateObserved(records, target)\n\tif err != nil {\n\t\treturn Report{}, err","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/cachebench/observed.go#L34-L70","documentation":"A trace record's prefix metadata is inconsistent: StableSegmentCount is negative or exceeds len(Prefix), or the Prefix array itself fails validPrefix. Prefix and StableSegmentCount drive cache-reuse math, so an impossible combination is rejected before evaluation.","triggerScenarios":"EvaluateObservedAgainstTrace on a trace record where StableSegmentCount < 0, StableSegmentCount > len(request.Prefix), or the prefix segments are malformed (bad segment shape/content per validPrefix).","commonSituations":"Trace records written by an older tool version with a different prefix segment schema; hand-adjusted stable_segment_count; prefix arrays truncated during file edits.","solutions":["Set stable_segment_count to a value in [0, len(prefix)] — typically the number of leading stable segments.","Regenerate the trace with the current version so prefix segments match validPrefix's expected shape.","Validate prefix arrays with the package's own helpers in a pre-flight pass before evaluation."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"func validTracePrefix(r TraceRecord) error {\n\tif r.StableSegmentCount < 0 || r.StableSegmentCount > len(r.Prefix) || !validPrefix(r.Prefix) {\n\t\treturn fmt.Errorf(\"request %q has invalid prefix\", r.RequestID)\n\t}\n\treturn nil\n}","typeGuard":"func prefixInRange(count, prefixLen int) bool {\n\treturn count >= 0 && count <= prefixLen\n}","tryCatchPattern":null,"preventionTips":["Derive stable_segment_count from the prefix array at generation, never hand-edit it.","Regenerate traces after tool upgrades that change the prefix schema.","Round-trip traces through the validator in tests."],"tags":["go","cachebench","prefix","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}