{"record":{"id":"2d7798ad5b55a85a","repo":"JuliusBrussee/caveman","slug":"cacheengine-invalid-cache-economics","errorCode":null,"errorMessage":"cacheengine: invalid cache economics","messagePattern":"cacheengine: invalid cache economics","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cacheengine/engine.go","lineNumber":298,"sourceCode":"\t}\n\tprofile := normalizedProfile(request.Profile)\n\tif !validIdentity(profile.ID, 256, false) || !validIdentity(profile.Provider, 64, true) || !validIdentity(profile.OptimizerID, 256, true) {\n\t\treturn errors.New(\"cacheengine: invalid profile identity\")\n\t}\n\tif profile.Mode != ModeUnsupported && profile.Mode != ModeImplicit && profile.Mode != ModeAffinity && profile.Mode != ModeExplicit {\n\t\treturn fmt.Errorf(\"cacheengine: unknown mode %q\", profile.Mode)\n\t}\n\tif profile.Mode != ModeUnsupported {\n\t\tif profile.MaxBreakpoints <= 0 || profile.MinPrefixTokens < 0 || profile.MaxRPMPerKey < 0 || profile.TTL < 0 {\n\t\t\treturn errors.New(\"cacheengine: invalid cache thresholds\")\n\t\t}\n\t\tswitch profile.Attribution {\n\t\tcase AttributionNone, AttributionOrganic, AttributionAffinity, AttributionCausal:\n\t\tdefault:\n\t\t\treturn fmt.Errorf(\"cacheengine: unknown attribution %q\", profile.Attribution)\n\t\t}\n\t\tif profile.EconomicsKnown && (!finiteNonNegative(profile.WriteMultiplier) || !finiteNonNegative(profile.ReadMultiplier)) {\n\t\t\treturn errors.New(\"cacheengine: invalid cache economics\")\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc normalizedProfile(profile Profile) Profile {\n\tif profile.Mode == ModeUnsupported {\n\t\tif profile.ID == \"\" {\n\t\t\tprofile.ID = \"unsupported\"\n\t\t}\n\t\treturn profile\n\t}\n\tif profile.MaxBreakpoints == 0 {\n\t\tprofile.MaxBreakpoints = 1\n\t}\n\tif profile.MaxRPMPerKey == 0 {\n\t\tprofile.MaxRPMPerKey = 15\n\t}","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/cacheengine/engine.go#L280-L316","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nprofile.WriteMultiplier = writeCost / float64(n) // NaN when n == 0\nprofile.EconomicsKnown = true\n\n// after\nif n > 0 {\n    profile.WriteMultiplier = writeCost / float64(n)\n    profile.ReadMultiplier = readCost / float64(n)\n    profile.EconomicsKnown = !math.IsNaN(profile.WriteMultiplier) && !math.IsInf(profile.WriteMultiplier, 0) && profile.WriteMultiplier >= 0\n}","handlingStrategy":"validation","validationCode":"func economicsOK(p cacheengine.Profile) bool {\n    return !p.EconomicsKnown || (finiteNonNeg(p.WriteMultiplier) && finiteNonNeg(p.ReadMultiplier))\n}\nfunc finiteNonNeg(f float64) bool { return !math.IsNaN(f) && !math.IsInf(f, 0) && f >= 0 }","typeGuard":"// n/a","tryCatchPattern":null,"preventionTips":["Guard zero denominators when deriving multipliers","Leave EconomicsKnown false when pricing data is missing"],"tags":["cacheengine","validation","float-safety","economics","go"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}