gofiber/fiber · error
cache: failed to delete raw key %q after store error: %w
Error message
cache: failed to delete raw key %q after store error: %w
What it means
Raised by cleanupOnStoreError during the store path: an entry was being written, manager.setRaw for the '_body' raw key (or the main set) succeeded but the subsequent set failed, so cleanup tries to manager.del the raw '_body' key it just stored — and that delete also failed. The returned error joins the original store error with this cleanup error so neither is hidden.
Source
Thrown at middleware/cache/cache.go:853
spaceReserved = false // Clear flag to prevent defer from unreserving
mux.Unlock()
}
cleanupOnStoreError := func(ctx context.Context, releaseEntry, rawStored bool) error {
var cleanupErr error
if cfg.MaxBytes > 0 {
mux.Lock()
_, size := heap.remove(heapIdx)
storedBytes -= size
mux.Unlock()
}
if releaseEntry {
manager.release(e)
}
if rawStored {
rawKey := key + "_body"
if err := manager.del(ctx, rawKey); err != nil {
cleanupErr = errors.Join(cleanupErr, fmt.Errorf("cache: failed to delete raw key %q after store error: %w", maskKey(rawKey), err))
}
}
return cleanupErr
}
// For external Storage we store raw body separated
if cfg.Storage != nil {
if err := manager.setRaw(reqCtx, key+"_body", e.body, storageExpiration); err != nil {
if cleanupErr := cleanupOnStoreError(reqCtx, true, false); cleanupErr != nil {
err = errors.Join(err, cleanupErr)
}
return err
}
// avoid body msgp encoding
e.body = nil
if err := manager.set(reqCtx, key, e, storageExpiration); err != nil {
if cleanupErr := cleanupOnStoreError(reqCtx, false, true); cleanupErr != nil {
err = errors.Join(err, cleanupErr)View on GitHub (pinned to 9a4c7e57fe)
Solutions
- Stabilize the storage backend (capacity, connectivity, ACLs) — both writes and deletes are unreliable.
- Out-of-band, flush orphaned '<key>_body' raw entries that the failed cleanup left behind.
- Reduce per-entry size (cap response bodies via cfg.MaxBytes) to avoid partial-store situations.
- If persistent, switch temporarily to in-memory cache (cfg.Storage == nil) which has no separate raw key.
Example fix
// before: external storage partially stores then fails cleanup
cfg := cache.Config{Storage: unstableStorage}
// after: healthy storage + body size cap
cfg := cache.Config{
Storage: stableStorage,
MaxBytes: 1 << 20, // cap per-entry / total bytes
Expiration: 5 * time.Minute,
} Defensive patterns
Strategy: try-catch
Validate before calling
func pingStorageSetDelete(s fiber.Storage) error {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
k := []byte("__ping_body__")
if err := s.Set(ctx, string(k), []byte("x"), 5*time.Second); err != nil {
return err
}
return s.Delete(ctx, string(k))
} Type guard
null
Try / catch
app.Use(func(c fiber.Ctx) error {
err := c.Next()
if err != nil && strings.Contains(err.Error(), "failed to delete raw key") {
log.Errorf("cache store + cleanup failed: %v", err)
return c.Status(fiber.StatusServiceUnavailable).SendString("cache unavailable")
}
return err
}) Prevention
- Cap response body size with cfg.MaxBytes to avoid partial-store situations.
- Keep storage capacity healthy so set and del both succeed.
- Out-of-band, sweep orphaned '<key>_body' raw entries left by failed cleanups.
- Temporarily use in-memory cache (cfg.Storage == nil) if the backend is unreliable.
When it happens
Trigger: cfg.Storage != nil (external storage); setRaw of key+'_body' succeeded but manager.set(key, e) failed; the compensating manager.del of key+'_body' also failed. Reproducible by failing both set and del on the storage driver while caching a response body.
Common situations: Storage backend degrades mid-write (disk fills between setRaw and set); TLS connection reset means the follow-up del also fails; Redis failover window; an entry slightly over a quota where setRaw fit but set (msgp-encoded item) didn't, then del also broke.
Related errors
- cache: failed to restore heap index for key %q: %w
- cache: failed to delete key %q while evicting: %w
- cache: failed to reload key %q after eviction failure: %w
- cache: failed to delete expired key %q: %w
- cache: failed to delete private response for key %q: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/da9179e14f929dcc.json.
Report an issue: GitHub.