{"id":"a80c0a82968ca269","repo":"gofiber/fiber","slug":"cache-failed-to-restore-heap-index-for-key-q-w","errorCode":null,"errorMessage":"cache: failed to restore heap index for key %q: %w","messagePattern":"cache: failed to restore heap index for key %q: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/cache/cache.go","lineNumber":196,"sourceCode":"\t\t_, size := heap.remove(heapIdx)\n\t\tstoredBytes -= size\n\t}\n\n\trefreshHeapIndex := func(ctx context.Context, candidate evictionCandidate) error {\n\t\tentry, err := manager.get(ctx, candidate.key)\n\t\tif err != nil {\n\t\t\tif errors.Is(err, errCacheMiss) {\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"cache: failed to reload key %q after eviction failure: %w\", maskKey(candidate.key), err)\n\t\t}\n\n\t\tentry.heapidx = candidate.heapIdx\n\n\t\tremainingTTL := max(secondsToTime(entry.exp).Sub(cfg.now()), 0)\n\n\t\tif err := manager.set(ctx, candidate.key, entry, remainingTTL); err != nil {\n\t\t\treturn fmt.Errorf(\"cache: failed to restore heap index for key %q: %w\", maskKey(candidate.key), err)\n\t\t}\n\n\t\treturn nil\n\t}\n\n\t// Return new handler\n\treturn func(c fiber.Ctx) error {\n\t\thasAuthorization := len(c.Request().Header.Peek(fiber.HeaderAuthorization)) > 0\n\t\treqCacheControl := c.Request().Header.Peek(fiber.HeaderCacheControl)\n\t\treqDirectives := parseRequestCacheControl(reqCacheControl)\n\t\tif !reqDirectives.noCache {\n\t\t\treqPragma := utils.UnsafeString(c.Request().Header.Peek(fiber.HeaderPragma))\n\t\t\tif hasDirective(reqPragma, noCache) {\n\t\t\t\treqDirectives.noCache = true\n\t\t\t}\n\t\t}\n\n\t\t// Refrain from caching","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/cache/cache.go#L178-L214","documentation":"Companion to the previous error, also inside refreshHeapIndex: after successfully re-reading the entry, manager.set failed while writing back the updated heapidx. The storage backend rejected the write, so the heap/index inconsistency could not be repaired. The wrapped error carries the storage driver's failure reason.","triggerScenarios":"Same eviction-rollback path as error 129, but manager.get succeeded and manager.set failed — e.g. storage is read-OK but write-blocked (disk full, read-replica, write-quorum lost). Forcible by injecting a set failure in the storage mock during eviction recovery.","commonSituations":"Redis cluster in a failover window (reads from replica, writes fail); SQLite storage on a full disk; storage connection read-timeout configured but write-timeout too small; replica-only storage accidentally wired into cache.","solutions":["Verify the storage backend accepts writes and has capacity (disk space, cluster health, WLM quotas).","Increase the storage driver's write/timeout settings to tolerate the load.","Reduce eviction pressure by increasing MaxBytes or lowering cacheable body sizes.","If persistent, drain and reseed the cache (clear storage + restart) to remove any half-written entries."],"exampleFix":"// before: storage write fails on rollback\nstorage := sqlite.New(...) // read-only mount\n\n// after: writable storage with healthy capacity\nstorage := sqlite.New(sqlite.Config{\n  Path: \"/var/lib/app/cache.db\",\n  // ensure dir is writable and disk has free space\n})","handlingStrategy":"try-catch","validationCode":"func pingStorage(s fiber.Storage) error {\n    ctx, cancel := context.WithTimeout(context.Background(), time.Second)\n    defer cancel()\n    if err := s.Set(ctx, \"__ping__\", []byte(\"1\"), 5*time.Second); err != nil {\n        return fmt.Errorf(\"storage write check: %w\", err)\n    }\n    return s.Delete(ctx, \"__ping__\")\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 restore heap index\") {\n        log.Warnf(\"cache write rollback failed: %v\", err)\n        return nil // degrade gracefully\n    }\n    return err\n})","preventionTips":["Ensure the storage backend accepts writes (writable disk, healthy cluster, not a read-replica).","Size storage timeouts to tolerate write load during eviction.","Reduce eviction pressure via larger MaxBytes or smaller cacheable bodies.","Flush and reseed storage after driver/encoding upgrades."],"tags":["cache","storage","eviction","write-failure","bookkeeping"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}