{"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":null,"severity":"warning","filePath":"middleware/cache/cache.go","lineNumber":538,"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\tc.Set(cfg.CacheHeader, cacheUnreachable)\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":520,"sourceCodeEnd":556,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/cache/cache.go#L520-L556","documentation":"On the response-write path: an existing cached entry exists and the new response carries Cache-Control: private, no-cache, or Vary: *, all of which make it uncacheable. Fiber tries to delete the old entry to honor RFC 9111 and deleteKey failed. The response is still sent to the client (c.Set CacheHeader=cacheUnreachable) but the stale entry remains in storage.","triggerScenarios":"A cached entry exists for a key; the origin now returns 'Cache-Control: private' (or 'no-cache' / 'Vary: *') for that key; deleteKey is called and manager.del returns an error. Triggered by upstream cache-control policy changes coinciding with a storage Delete failure.","commonSituations":"Origin tightens its cache-control (login-gated content); two responses racing for the same key where one is private; storage backend transiently unavailable; switching storage drivers without flushing the old entries.","solutions":["Resolve the underlying storage Delete failure (see wrapped %w).","Flush the storage so previously-cached entries that should no longer be cached are removed out of band.","Align upstream cache-control so it doesn't oscillate between cacheable and private/no-cache for the same route.","Consider cfg.Next to bypass caching for known-private routes, removing the delete-on-conflict path entirely."],"exampleFix":"// before: storage Delete fails purging old entry on private response\ncfg := cache.Config{Storage: flakyStorage}\n\n// after: skip cache for private routes + robust storage\ncfg := cache.Config{\n  Storage: robustStorage,\n  Next: func(c fiber.Ctx) bool {\n    return c.Path() == \"/me\" // known-private route\n  },\n}","handlingStrategy":"validation","validationCode":"// Skip caching routes that frequently return private/no-cache.\ncfg := cache.Config{\n  Next: func(c fiber.Ctx) bool {\n    return c.Path() == \"/login\" || c.Path() == \"/account\"\n  },\n}","typeGuard":"null","tryCatchPattern":"app.Use(func(c fiber.Ctx) error {\n    err := c.Next()\n    if err != nil && strings.Contains(err.Error(), \"failed to delete cached response\") {\n        log.Warnf(\"uncacheable-response purge failed: %v\", err)\n        return nil\n    }\n    return err\n})","preventionTips":["Keep origin cache-control policy stable per route.","Bypass caching for known-private routes via cfg.Next.","Flush storage when origin cache-control semantics change.","Diagnose wrapped storage Delete errors before they recur."],"tags":["cache","storage","private","no-cache","delete","cache-control"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}