{"record":{"id":"0c31d18097c91ae1","repo":"JuliusBrussee/caveman","slug":"provider-response-invalid","errorCode":"provider_response_invalid","errorMessage":"cachebench: provider returned invalid request identity for %q","messagePattern":"cachebench: provider returned invalid request identity for %q","errorType":"validation","errorClass":"ReplayRunError","httpStatus":null,"severity":"error","filePath":"cacheengine/cachebench/replay.go","lineNumber":702,"sourceCode":"\t\treturn ReplayResult{Evidence: evidence, ProviderResponse: append([]byte(nil), response.Body...)}, &ReplayRunError{\n\t\t\tRequestID: record.RequestID, FailureCode: evidence.FailureCode,\n\t\t\tErr: fmt.Errorf(\"cachebench: clock regressed while replaying %q\", record.RequestID),\n\t\t}\n\t}\n\tevidence.CompletedAt = completed.Format(time.RFC3339Nano)\n\tevidence.LatencyMilliseconds = completed.Sub(started).Milliseconds()\n\tif sendErr != nil {\n\t\tevidence.FailureCode = \"transport_error\"\n\t\treturn ReplayResult{Evidence: evidence, ProviderResponse: append([]byte(nil), response.Body...)}, &ReplayRunError{\n\t\t\tRequestID: record.RequestID, FailureCode: evidence.FailureCode,\n\t\t\tErr: fmt.Errorf(\"cachebench: provider transport failed for %q: %w\", record.RequestID, sendErr),\n\t\t}\n\t}\n\tif !validProviderRequestID(response.ProviderRequestID) {\n\t\tevidence.FailureCode = \"provider_response_invalid\"\n\t\treturn ReplayResult{Evidence: evidence, ProviderResponse: append([]byte(nil), response.Body...)}, &ReplayRunError{\n\t\t\tRequestID: record.RequestID, FailureCode: evidence.FailureCode,\n\t\t\tErr: fmt.Errorf(\"cachebench: provider returned invalid request identity for %q\", record.RequestID),\n\t\t}\n\t}\n\tevidence.ProviderRequestID = response.ProviderRequestID\n\tif response.StatusCode < 200 || response.StatusCode >= 300 {\n\t\tevidence.FailureCode = \"provider_http_status\"\n\t\treturn ReplayResult{Evidence: evidence, ProviderResponse: append([]byte(nil), response.Body...)}, &ReplayRunError{\n\t\t\tRequestID: record.RequestID, FailureCode: evidence.FailureCode,\n\t\t\tErr: fmt.Errorf(\"cachebench: provider returned HTTP %d for %q\", response.StatusCode, record.RequestID),\n\t\t}\n\t}\n\tusage, ok := cacheengine.ExtractProviderUsage(record.Provider, response.Body)\n\tif !ok {\n\t\tevidence.FailureCode = \"provider_usage_invalid\"\n\t\treturn ReplayResult{Evidence: evidence, ProviderResponse: append([]byte(nil), response.Body...)}, &ReplayRunError{\n\t\t\tRequestID: record.RequestID, FailureCode: evidence.FailureCode,\n\t\t\tErr: fmt.Errorf(\"cachebench: provider usage unavailable for %q\", record.RequestID),\n\t\t}\n\t}","sourceCodeStart":684,"sourceCodeEnd":720,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/cachebench/replay.go#L684-L720","documentation":"The transport succeeded but response.ProviderRequestID failed the validProviderRequestID check (empty or malformed). Every replayed request must carry a verifiable provider-side request identity for audit evidence, so the request fails with FailureCode provider_response_invalid even if the HTTP call itself was fine.","triggerScenarios":"A Transport implementation that returns a ReplayResponse without setting ProviderRequestID (e.g. a stub/mock transport), or a provider/endpoint that does not echo a request id header; an id containing only whitespace or invalid characters.","commonSituations":"Custom test transports forgetting to populate the field; pointing replay at a provider emulator that lacks the request-id header; header name changes after a provider API update so the transport extracts nothing.","solutions":["Fix the Transport to populate ReplayResponse.ProviderRequestID from the provider's request-id header (e.g. request-id / x-request-id).","If replaying against an emulator, make it return a well-formed id.","Verify the header name still matches the provider's current API documentation after upgrades.","If you control the contract, validate the id format (non-empty, expected charset) inside the transport before returning."],"exampleFix":"// before\nreturn cachebench.ReplayResponse{StatusCode: 200, Body: body}, nil // no ProviderRequestID\n\n// after\nreturn cachebench.ReplayResponse{StatusCode: 200, Body: body, ProviderRequestID: resp.Header.Get(\"request-id\")}, nil","handlingStrategy":"validation","validationCode":"func providerIDPresent(id string) bool {\n    return strings.TrimSpace(id) != \"\"\n}","typeGuard":"func isProviderResponseInvalid(err error) bool {\n    var rre *cachebench.ReplayRunError\n    return errors.As(err, &rre) && rre.FailureCode == \"provider_response_invalid\"\n}","tryCatchPattern":"if err := runner.Run(ctx, records, emit); err != nil {\n    if isProviderResponseInvalid(err) {\n        // transport returned no ProviderRequestID; fix header extraction in the transport\n    }\n    return err\n}","preventionTips":["Unit-test custom transports: assert ProviderRequestID is populated from the provider's id header.","Emulators used for replay must echo a well-formed request id.","Re-check header names after provider API upgrades."],"tags":["cachebench","transport","provider-api","validation"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}