gofiber/fiber · warning

cache: failed to delete private response for key

Error message

cache: failed to delete private response for key %q: %w

What it means

Returned from the request hot path when a cached entry is found to be private (Authorization/Cache-Control: private triggered entryHasPrivate) and the subsequent deleteKey fails. Private responses must not be served from a shared cache, so Fiber attempts to purge the stored entry; a storage delete failure means the private entry could persist and leak, hence the explicit error.

Solutions

  1. Ensure Vary headers (Authorization at minimum) are honored so private responses get distinct keys: do not set cfg.DisableVaryHeaders.
  2. Diagnose the wrapped delete error against the storage backend.
  3. Audit upstream Cache-Control: private usage to confirm caching is intentional.
  4. Confirm storage connectivity and delete permissions.
  5. Reproduce with logging that prints the (masked) key to correlate with Vary mismatch.

Example fix

// before: vary disabled, private responses collide with public ones
cfg := cache.Config{DisableVaryHeaders: true}

// after: keep vary enabled so Authorization yields a distinct key
cfg := cache.Config{CacheControl: true}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure Vary is honored so private responses do not collide with public ones.
func validateCacheConfig(cfg cache.Config) error {
    if cfg.DisableVaryHeaders {
        // risky: private responses may share a key with public ones
        return fmt.Errorf("DisableVaryHeaders must be false when caching authenticated responses")
    }
    return nil
}

Try / catch

app.Use(func(c fiber.Ctx) error {
    err := c.Next()
    if err != nil && isCachePrivateDeleteErr(err) {
        // do not serve the cached private response; fall through
        return nil
    }
    return err
})

Prevention

When it happens

Trigger: A response previously cached is later classified private (e.g. an Authorization header appeared on the request, or the response's Cache-Control: private was just observed), and the storage Delete for that key fails. The cache sets the CacheHeader to cacheUnreachable and, if only-if-cached was requested, returns 504.

Common situations: Mixed-content caching where some responses are public and others private under the same key shape; storage blip during the private purge; misconfigured Vary so private and public responses collide on a key; client sending Authorization on a previously-public cached resource.

Related errors


AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11). Data as JSON: /api/errors/c161b3e7f6b9aecb. Report an issue: GitHub.

Appendix: source

Thrown at middleware/cache/cache.go:448

				unlock()
				if err := deleteKey(reqCtx, key); err != nil {
					if e != nil {
						manager.release(e)
					}
					return fmt.Errorf("cache: failed to delete expired key %q: %w", maskKey(key), err)
				}
				relock()
				idx := e.heapidx
				manager.release(e)
				removeHeapEntry(key, idx)
				e = nil
			case entryHasPrivate:
				unlock()
				if err := deleteKey(reqCtx, key); err != nil {
					if e != nil {
						manager.release(e)
					}
					return fmt.Errorf("cache: failed to delete private response for key %q: %w", maskKey(key), err)
				}
				relock()
				removeHeapEntry(key, e.heapidx)
				if cfg.Storage != nil && e != nil {
					manager.release(e)
				}
				e = nil
				unlock()
				c.Set(cfg.CacheHeader, cacheUnreachable)
				if reqDirectives.onlyIfCached {
					return c.SendStatus(fiber.StatusGatewayTimeout)
				}
				return c.Next()
			case entryHasExpiration && !requestNoCache:
				servedStale = entryExpired
				if hasAuthorization && !e.shareable {
					if cfg.Storage != nil {
						manager.release(e)

View on GitHub (pinned to a105acad6c)