{"record":{"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":500,"severity":"warning","filePath":"middleware/cache/cache.go","lineNumber":219,"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\t// Every field line, like the hash below: an empty first Authorization line\n\t\t// would otherwise read as anonymous. canonical is app config, fixed for the\n\t\t// life of the handler, so read it once.\n\t\tcanonical := headerlookup.Canonical(c)\n\n\t\thasAuthorization := false\n\t\tfor _, v := range fieldname.Lines(&c.Request().Header, fiber.HeaderAuthorization, canonical) {\n\t\t\tif len(v) > 0 {\n\t\t\t\thasAuthorization = true\n\t\t\t\tbreak\n\t\t\t}","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/cache/cache.go#L201-L237","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: redis with maxmemory-policy noeviction\nCONFIG SET maxmemory-policy noeviction\n\n// after\nCONFIG SET maxmemory-policy allkeys-lru\n// and/or raise maxmemory","handlingStrategy":"validation","validationCode":"// Validate storage write capacity before enabling MaxBytes eviction.\nfunc canWriteAtScale(s fiber.Storage, n int) error {\n    for i := 0; i < n; i++ {\n        if err := s.Set(fmt.Sprintf(\"probe:%d\", i), []byte(\"x\"), time.Minute); err != nil {\n            return fmt.Errorf(\"storage write probe %d failed: %w\", i, err)\n        }\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["cache","storage","eviction","redis","distributed","write-failure"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}