gofiber/fiber · warning

cache: failed to delete cached response for key

Error message

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

What it means

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.

Solutions

  1. Verify the upstream Cache-Control / Vary policy is what you intended (no-cache/private/Vary:* may be a misconfiguration).
  2. Diagnose the wrapped delete error against the storage backend.
  3. Ensure storage connectivity and delete permissions for the cache namespace.
  4. If Vary: * is intentional, accept that the response is uncacheable and the prior entry purge must succeed; harden storage.
  5. Add storage delete monitoring to catch the underlying cause.

Example fix

// before: upstream set Vary: * by mistake, causing repeated purge churn
Cache-Control: private
Vary: *

// after: scope Vary to actual headers
Vary: Authorization
Defensive patterns

Strategy: validation

Validate before calling

// Audit upstream Cache-Control/Vary policy so the cache does not churn.
func classify(respHeaders http.Header) string {
    cc := respHeaders.Get("Cache-Control")
    switch {
    case strings.Contains(cc, "no-cache"): return "no-cache"
    case strings.Contains(cc, "private"): return "private"
    case respHeaders.Get("Vary") == "*": return "vary:*"
    }
    return "cacheable"
}

Try / catch

app.Use(func(c fiber.Ctx) error {
    err := c.Next()
    if err != nil && isCacheUncacheableDeleteErr(err) {
        // origin said do-not-cache; serve uncached and move on
        return nil
    }
    return err
})

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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

Appendix: source

Thrown at middleware/cache/cache.go:620

		hasPrivate := respCacheControl.hasPrivate
		hasNoCache := respCacheControl.hasNoCache
		varyNames, varyHasStar := parseVary(varyHeader)

		// Respect server cache-control: no-store
		if respCacheControl.hasNoStore {
			markUnreachable()
			return nil
		}

		// RFC 9111 requires responses with Vary: * to remain uncacheable even when
		// response-driven Vary partitioning is otherwise disabled.
		if hasPrivate || hasNoCache || varyHasStar {
			if e != nil {
				if err := deleteKey(reqCtx, key); err != nil {
					if cfg.Storage != nil {
						manager.release(e)
					}
					return fmt.Errorf("cache: failed to delete cached response for key %q: %w", maskKey(key), err)
				}
				mux.Lock()
				removeHeapEntry(key, e.heapidx)
				if cfg.Storage != nil {
					manager.release(e)
				}
				e = nil
				mux.Unlock()
			}

			if !cfg.DisableVaryHeaders && hasVaryManifest {
				if err := manager.del(reqCtx, manifestKey); err != nil {
					return fmt.Errorf("cache: failed to delete stale vary manifest %q: %w", maskKey(manifestKey), err)
				}
			}

			c.Set(cfg.CacheHeader, cacheUnreachable)
			return nil

View on GitHub (pinned to a105acad6c)