{"record":{"id":"e0712401ee66766f","repo":"JuliusBrussee/caveman","slug":"engine-not-cacheable","errorCode":"engine_not_cacheable","errorMessage":"cachebench: request %q is not cacheable: %s","messagePattern":"cachebench: request %q is not cacheable: (.+?)","errorType":"exception","errorClass":"ReplayRunError","httpStatus":null,"severity":"error","filePath":"cacheengine/cachebench/replay.go","lineNumber":528,"sourceCode":"\t\t}\n\t\toptimized, err := runner.Engine.Optimize(ctx, native)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cachebench: optimize request %q: %w\", record.RequestID, err)\n\t\t}\n\t\tequivalent := bytes.Equal(native.Body, optimized.Body)\n\t\tif optimized.Applied {\n\t\t\tequivalent = ModelVisibleEquivalent(native.Body, optimized.Body)\n\t\t}\n\t\tif !equivalent {\n\t\t\treturn nil, &ReplayRunError{\n\t\t\t\tRequestID: record.RequestID, FailureCode: \"model_visible_mismatch\",\n\t\t\t\tErr: fmt.Errorf(\"cachebench: request %q failed model-visible equivalence\", record.RequestID),\n\t\t\t}\n\t\t}\n\t\tif optimized.Decision != cacheengine.DecisionApply && optimized.Decision != cacheengine.DecisionObserveOnly && optimized.Reason != cacheengine.ReasonBelowMinimum {\n\t\t\treturn nil, &ReplayRunError{\n\t\t\t\tRequestID: record.RequestID, FailureCode: \"engine_not_cacheable\",\n\t\t\t\tErr: fmt.Errorf(\"cachebench: request %q is not cacheable: %s\", record.RequestID, optimized.Reason),\n\t\t\t}\n\t\t}\n\t\tprepared = append(prepared, preparedReplay{record: record, optimized: optimized})\n\t}\n\treturn prepared, nil\n}\n\nfunc validatePreparedReplayTarget(prepared []preparedReplay, target Target) error {\n\tif err := validateTarget(target); err != nil {\n\t\treturn err\n\t}\n\tproviders := map[string]bool{}\n\teligible := map[string]int{}\n\tfor _, item := range prepared {\n\t\tprovider := strings.ToLower(strings.TrimSpace(item.record.Provider))\n\t\tproviders[provider] = true\n\t\tif item.optimized.Decision == cacheengine.DecisionApply || item.optimized.Decision == cacheengine.DecisionObserveOnly {\n\t\t\teligible[provider]++","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/cachebench/replay.go#L510-L546","documentation":"After optimization, the record's Decision is neither DecisionApply nor DecisionObserveOnly, and its Reason is not ReasonBelowMinimum — the engine judged the request not cache-eligible for some other reason. The replay gate requires every prepared request to be cacheable (or explicitly below the minimum-size threshold), so preparation fails with FailureCode engine_not_cacheable and the engine's reason string.","triggerScenarios":"A trace containing requests the engine refuses to cache: unsupported endpoints, non-cacheable content types, streaming-only requests, or any engine-specific rejection reason surfaced via optimized.Reason.","commonSituations":"Replaying a production trace that includes mixed workloads (some cache-ineligible) against strict engine rules; engine rules tightened between capture and replay; a new endpoint not yet whitelisted as cacheable.","solutions":["Read the %s reason in the message — it is the engine's own rejection text for that request.","Filter the trace before replay to requests the engine deems cacheable (dry-run Optimize per record and keep Decision Apply/ObserveOnly or Reason BelowMinimum).","Loosen engine eligibility rules if the rejected class of requests should be cacheable.","Re-check populations after filtering, or error 886 (eligible minimum) will fire next."],"exampleFix":"// before\nerr := runner.Run(ctx, allRecords, emit) // trace contains non-cacheable rows\n\n// after\nvar cacheable []cachebench.TraceRecord\nfor _, r := range allRecords {\n    if ok, _ := engineEligible(ctx, engine, r); ok { cacheable = append(cacheable, r) }\n}\nerr := runner.Run(ctx, cacheable, emit)","handlingStrategy":"validation","validationCode":"var keep []cachebench.TraceRecord\nfor _, r := range records {\n    native, err := r.NativeRequest()\n    if err != nil { continue }\n    opt, err := engine.Optimize(ctx, native)\n    if err != nil { continue }\n    if opt.Decision == cacheengine.DecisionApply || opt.Decision == cacheengine.DecisionObserveOnly || opt.Reason == cacheengine.ReasonBelowMinimum {\n        keep = append(keep, r)\n    }\n}\nrecords = keep","typeGuard":"func isEngineNotCacheable(err error) bool {\n    var rre *cachebench.ReplayRunError\n    return errors.As(err, &rre) && rre.FailureCode == \"engine_not_cacheable\"\n}","tryCatchPattern":"if err := runner.Run(ctx, records, emit); err != nil {\n    if isEngineNotCacheable(err) {\n        // read the reason string; filter trace or relax engine rules, then retry\n    }\n    return err\n}","preventionTips":["Dry-run Optimize over the trace and filter to cacheable records before replay.","Track engine rejection reasons in capture pipelines so traces stay replay-clean.","After filtering, re-check per-provider minimums to avoid error 886."],"tags":["cachebench","eligibility","engine","replay"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}