JuliusBrussee/caveman · error · ReplayRunError
engine_not_cacheable
engine_not_cacheable
Error message
cachebench: request %q is not cacheable: %s
What it means
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.
Source
Thrown at cacheengine/cachebench/replay.go:528
}
optimized, err := runner.Engine.Optimize(ctx, native)
if err != nil {
return nil, fmt.Errorf("cachebench: optimize request %q: %w", record.RequestID, err)
}
equivalent := bytes.Equal(native.Body, optimized.Body)
if optimized.Applied {
equivalent = ModelVisibleEquivalent(native.Body, optimized.Body)
}
if !equivalent {
return nil, &ReplayRunError{
RequestID: record.RequestID, FailureCode: "model_visible_mismatch",
Err: fmt.Errorf("cachebench: request %q failed model-visible equivalence", record.RequestID),
}
}
if optimized.Decision != cacheengine.DecisionApply && optimized.Decision != cacheengine.DecisionObserveOnly && optimized.Reason != cacheengine.ReasonBelowMinimum {
return nil, &ReplayRunError{
RequestID: record.RequestID, FailureCode: "engine_not_cacheable",
Err: fmt.Errorf("cachebench: request %q is not cacheable: %s", record.RequestID, optimized.Reason),
}
}
prepared = append(prepared, preparedReplay{record: record, optimized: optimized})
}
return prepared, nil
}
func validatePreparedReplayTarget(prepared []preparedReplay, target Target) error {
if err := validateTarget(target); err != nil {
return err
}
providers := map[string]bool{}
eligible := map[string]int{}
for _, item := range prepared {
provider := strings.ToLower(strings.TrimSpace(item.record.Provider))
providers[provider] = true
if item.optimized.Decision == cacheengine.DecisionApply || item.optimized.Decision == cacheengine.DecisionObserveOnly {
eligible[provider]++View on GitHub (pinned to 27d5a3981a)
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.
Example fix
// before
err := runner.Run(ctx, allRecords, emit) // trace contains non-cacheable rows
// after
var cacheable []cachebench.TraceRecord
for _, r := range allRecords {
if ok, _ := engineEligible(ctx, engine, r); ok { cacheable = append(cacheable, r) }
}
err := runner.Run(ctx, cacheable, emit) Defensive patterns
Strategy: validation
Validate before calling
var keep []cachebench.TraceRecord
for _, r := range records {
native, err := r.NativeRequest()
if err != nil { continue }
opt, err := engine.Optimize(ctx, native)
if err != nil { continue }
if opt.Decision == cacheengine.DecisionApply || opt.Decision == cacheengine.DecisionObserveOnly || opt.Reason == cacheengine.ReasonBelowMinimum {
keep = append(keep, r)
}
}
records = keep Type guard
func isEngineNotCacheable(err error) bool {
var rre *cachebench.ReplayRunError
return errors.As(err, &rre) && rre.FailureCode == "engine_not_cacheable"
} Try / catch
if err := runner.Run(ctx, records, emit); err != nil {
if isEngineNotCacheable(err) {
// read the reason string; filter trace or relax engine rules, then retry
}
return err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cachebench: optimize request %q: %w
- cachebench: provider %q engine-eligible population %d cannot
- cachebench: session %q request %d: %w
- cachebench: observation request %q body digest mismatch
- cachebench: replay request %q has empty provider
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/e0712401ee66766f.
Report an issue: GitHub.