JuliusBrussee/caveman · error
cacheengine: invalid cache economics
Error message
cacheengine: invalid cache economics
What it means
Thrown by validatePlanRequest when profile.EconomicsKnown is true but WriteMultiplier or ReadMultiplier is not a finite, non-negative float (NaN, +Inf, -Inf, or < 0). These multipliers price cache writes vs reads; non-finite economics would poison the net-gain math in breakpointCandidates.
Source
Thrown at cacheengine/engine.go:298
}
profile := normalizedProfile(request.Profile)
if !validIdentity(profile.ID, 256, false) || !validIdentity(profile.Provider, 64, true) || !validIdentity(profile.OptimizerID, 256, true) {
return errors.New("cacheengine: invalid profile identity")
}
if profile.Mode != ModeUnsupported && profile.Mode != ModeImplicit && profile.Mode != ModeAffinity && profile.Mode != ModeExplicit {
return fmt.Errorf("cacheengine: unknown mode %q", profile.Mode)
}
if profile.Mode != ModeUnsupported {
if profile.MaxBreakpoints <= 0 || profile.MinPrefixTokens < 0 || profile.MaxRPMPerKey < 0 || profile.TTL < 0 {
return errors.New("cacheengine: invalid cache thresholds")
}
switch profile.Attribution {
case AttributionNone, AttributionOrganic, AttributionAffinity, AttributionCausal:
default:
return fmt.Errorf("cacheengine: unknown attribution %q", profile.Attribution)
}
if profile.EconomicsKnown && (!finiteNonNegative(profile.WriteMultiplier) || !finiteNonNegative(profile.ReadMultiplier)) {
return errors.New("cacheengine: invalid cache economics")
}
}
return nil
}
func normalizedProfile(profile Profile) Profile {
if profile.Mode == ModeUnsupported {
if profile.ID == "" {
profile.ID = "unsupported"
}
return profile
}
if profile.MaxBreakpoints == 0 {
profile.MaxBreakpoints = 1
}
if profile.MaxRPMPerKey == 0 {
profile.MaxRPMPerKey = 15
}View on GitHub (pinned to 27d5a3981a)
Solutions
- Sanitize multipliers with math.IsNaN/math.IsInf and a >= 0 check before setting EconomicsKnown
- Fix the division/parse that produced NaN or Inf (guard zero denominators, reject 'NaN'/'Infinity' in config parsing)
- If you have no reliable pricing data, leave EconomicsKnown false so the check is skipped
Example fix
// before
profile.WriteMultiplier = writeCost / float64(n) // NaN when n == 0
profile.EconomicsKnown = true
// after
if n > 0 {
profile.WriteMultiplier = writeCost / float64(n)
profile.ReadMultiplier = readCost / float64(n)
profile.EconomicsKnown = !math.IsNaN(profile.WriteMultiplier) && !math.IsInf(profile.WriteMultiplier, 0) && profile.WriteMultiplier >= 0
} Defensive patterns
Strategy: validation
Validate before calling
func economicsOK(p cacheengine.Profile) bool {
return !p.EconomicsKnown || (finiteNonNeg(p.WriteMultiplier) && finiteNonNeg(p.ReadMultiplier))
}
func finiteNonNeg(f float64) bool { return !math.IsNaN(f) && !math.IsInf(f, 0) && f >= 0 } Type guard
// n/a
Prevention
- Guard zero denominators when deriving multipliers
- Leave EconomicsKnown false when pricing data is missing
When it happens
Trigger: Calling Plan with EconomicsKnown: true and a multiplier loaded from a computation that produced NaN/Inf (division by zero, parsing 'NaN' from JSON), or a negative multiplier from a sign error.
Common situations: Parsing multipliers from user/env config where 'NaN' or 'Infinity' is accepted by encoding/json into float64; computing price = cost/count with count == 0; upstream price API returning garbage that propagates into the profile.
Related errors
- cacheengine: cache economics overflow
- cacheengine: invalid partition key
- cacheengine: negative traffic expectation
- cacheengine: invalid profile identity
- cacheengine: invalid cache thresholds
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/2d7798ad5b55a85a.
Report an issue: GitHub.