gofiber/fiber · warning
cache: failed to restore heap index for key
Error message
cache: failed to restore heap index for key %q: %w
What it means
Returned by refreshHeapIndex when the entry WAS successfully re-read from storage but manager.set fails while writing back the restored heapidx. This is the second half of eviction rollback: read worked, write failed. The wrapped error is from the storage backend's Set operation (e.g. Redis SET failed, context canceled, TTL write rejected).
Solutions
- Check storage capacity and eviction policy: redis-cli INFO memory; if noeviction, raise maxmemory or pick an eviction policy.
- Inspect the wrapped Set error for backend-specific causes.
- Ensure the request context is not being canceled prematurely (long upstream handler holding the lock).
- Scale storage or shard the cache to reduce write pressure.
- Reproduce with the cache middleware's instrumentation enabled to correlate GET/SET timing.
Example fix
// before: redis with maxmemory-policy noeviction CONFIG SET maxmemory-policy noeviction // after CONFIG SET maxmemory-policy allkeys-lru // and/or raise maxmemory
Defensive patterns
Strategy: validation
Validate before calling
// Validate storage write capacity before enabling MaxBytes eviction.
func canWriteAtScale(s fiber.Storage, n int) error {
for i := 0; i < n; i++ {
if err := s.Set(fmt.Sprintf("probe:%d", i), []byte("x"), time.Minute); err != nil {
return fmt.Errorf("storage write probe %d failed: %w", i, err)
}
}
return nil
} Prevention
- If using Redis, avoid maxmemory-policy noeviction when writes are frequent.
- Keep storage write latency well below the request timeout.
- Ensure reqCtx is not canceled prematurely by upstream handlers.
- Right-size MaxBytes to reduce eviction-triggered Set pressure.
When it happens
Trigger: Backend accepts the GET but rejects the SET during eviction rollback: storage near capacity with eviction policy nosql-eviction-off, write blacklist, connection drop between GET and SET, or the request context expires between the two calls.
Common situations: Redis maxmemory-policy set to noeviction (writes fail when full); storage node failover between read and write; long TTL differences causing a SET to be rejected; network partition mid-request.
Related errors
- cache: failed to delete key
- cache: failed to reload key
- cache: failed to delete key
- failed to read response
- failed to save response
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/a80c0a82968ca269.
Report an issue: GitHub.
Appendix: source
Thrown at middleware/cache/cache.go:219
_, size := heap.remove(heapIdx)
storedBytes -= size
}
refreshHeapIndex := func(ctx context.Context, candidate evictionCandidate) error {
entry, err := manager.get(ctx, candidate.key)
if err != nil {
if errors.Is(err, errCacheMiss) {
return nil
}
return fmt.Errorf("cache: failed to reload key %q after eviction failure: %w", maskKey(candidate.key), err)
}
entry.heapidx = candidate.heapIdx
remainingTTL := max(secondsToTime(entry.exp).Sub(cfg.now()), 0)
if err := manager.set(ctx, candidate.key, entry, remainingTTL); err != nil {
return fmt.Errorf("cache: failed to restore heap index for key %q: %w", maskKey(candidate.key), err)
}
return nil
}
// Return new handler
return func(c fiber.Ctx) error {
// Every field line, like the hash below: an empty first Authorization line
// would otherwise read as anonymous. canonical is app config, fixed for the
// life of the handler, so read it once.
canonical := headerlookup.Canonical(c)
hasAuthorization := false
for _, v := range fieldname.Lines(&c.Request().Header, fiber.HeaderAuthorization, canonical) {
if len(v) > 0 {
hasAuthorization = true
break
}View on GitHub (pinned to a105acad6c)