{"record":{"id":"dcfd2e94b80aacf1","repo":"gofiber/fiber","slug":"cache-failed-to-delete-cached-response-for-key-q","errorCode":null,"errorMessage":"cache: failed to delete cached response for key %q: %w","messagePattern":"cache: failed to delete cached response for key %q: %w","errorType":"http","errorClass":null,"httpStatus":500,"severity":"warning","filePath":"middleware/cache/cache.go","lineNumber":620,"sourceCode":"\t\thasPrivate := respCacheControl.hasPrivate\n\t\thasNoCache := respCacheControl.hasNoCache\n\t\tvaryNames, varyHasStar := parseVary(varyHeader)\n\n\t\t// Respect server cache-control: no-store\n\t\tif respCacheControl.hasNoStore {\n\t\t\tmarkUnreachable()\n\t\t\treturn nil\n\t\t}\n\n\t\t// RFC 9111 requires responses with Vary: * to remain uncacheable even when\n\t\t// response-driven Vary partitioning is otherwise disabled.\n\t\tif hasPrivate || hasNoCache || varyHasStar {\n\t\t\tif e != nil {\n\t\t\t\tif err := deleteKey(reqCtx, key); err != nil {\n\t\t\t\t\tif cfg.Storage != nil {\n\t\t\t\t\t\tmanager.release(e)\n\t\t\t\t\t}\n\t\t\t\t\treturn fmt.Errorf(\"cache: failed to delete cached response for key %q: %w\", maskKey(key), err)\n\t\t\t\t}\n\t\t\t\tmux.Lock()\n\t\t\t\tremoveHeapEntry(key, e.heapidx)\n\t\t\t\tif cfg.Storage != nil {\n\t\t\t\t\tmanager.release(e)\n\t\t\t\t}\n\t\t\t\te = nil\n\t\t\t\tmux.Unlock()\n\t\t\t}\n\n\t\t\tif !cfg.DisableVaryHeaders && hasVaryManifest {\n\t\t\t\tif err := manager.del(reqCtx, manifestKey); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"cache: failed to delete stale vary manifest %q: %w\", maskKey(manifestKey), err)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tc.Set(cfg.CacheHeader, cacheUnreachable)\n\t\t\treturn nil","sourceCodeStart":602,"sourceCodeEnd":638,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/cache/cache.go#L602-L638","documentation":"Returned from the response-storage path when, after deciding the response must NOT be cached (hasPrivate || hasNoCache || varyHasStar), Fiber attempts to delete a previously-stored entry for that key and deleteKey fails. RFC 9111 requires Vary: * and private/no-cache responses to stay out of the cache, so any prior entry is purged; storage failure here is surfaced as an error rather than silently leaving stale data.","triggerScenarios":"A key that previously held a cacheable response is now classified uncacheable (origin returned Cache-Control: no-cache, private, or Vary: *), and the storage Delete fails. The error halts further processing of this response's storage; the heap entry is removed in-memory and the entry released before returning.","commonSituations":"Origin changed its Cache-Control policy for a route; storage backend briefly unavailable during policy transition; Vary header set to '*' by mistake in upstream; first private response after a long run of public ones.","solutions":["Verify the upstream Cache-Control / Vary policy is what you intended (no-cache/private/Vary:* may be a misconfiguration).","Diagnose the wrapped delete error against the storage backend.","Ensure storage connectivity and delete permissions for the cache namespace.","If Vary: * is intentional, accept that the response is uncacheable and the prior entry purge must succeed; harden storage.","Add storage delete monitoring to catch the underlying cause."],"exampleFix":"// before: upstream set Vary: * by mistake, causing repeated purge churn\nCache-Control: private\nVary: *\n\n// after: scope Vary to actual headers\nVary: Authorization","handlingStrategy":"validation","validationCode":"// Audit upstream Cache-Control/Vary policy so the cache does not churn.\nfunc classify(respHeaders http.Header) string {\n    cc := respHeaders.Get(\"Cache-Control\")\n    switch {\n    case strings.Contains(cc, \"no-cache\"): return \"no-cache\"\n    case strings.Contains(cc, \"private\"): return \"private\"\n    case respHeaders.Get(\"Vary\") == \"*\": return \"vary:*\"\n    }\n    return \"cacheable\"\n}","typeGuard":null,"tryCatchPattern":"app.Use(func(c fiber.Ctx) error {\n    err := c.Next()\n    if err != nil && isCacheUncacheableDeleteErr(err) {\n        // origin said do-not-cache; serve uncached and move on\n        return nil\n    }\n    return err\n})","preventionTips":["Verify upstream Cache-Control and Vary are intentional.","Avoid Vary: * unless you really mean 'never cache'.","Stabilize the policy per route to reduce purge churn.","Harden storage delete connectivity."],"tags":["cache","storage","delete","vary","no-cache","rfc-9111"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}