{"id":"f7b42bba9053962f","repo":"gofiber/fiber","slug":"cache-insufficient-space-and-no-entries-to-evict","errorCode":null,"errorMessage":"cache: insufficient space and no entries to evict","messagePattern":"cache: insufficient space and no entries to evict","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"middleware/cache/cache.go","lineNumber":631,"sourceCode":"\t\tif cfg.MaxBytes > 0 {\n\t\t\tmux.Lock()\n\t\t\t// Reserve space for the new entry first\n\t\t\tstoredBytes += bodySize\n\t\t\tspaceReserved = true\n\n\t\t\t// Now evict entries until we're under the limit\n\t\t\tvar keysToRemove []string\n\t\t\tvar sizesToRemove []uint\n\t\t\tvar candidates []evictionCandidate\n\n\t\t\tfor storedBytes > cfg.MaxBytes {\n\t\t\t\tif heap.Len() == 0 {\n\t\t\t\t\t// Can't evict more, unreserve space and fail\n\t\t\t\t\tstoredBytes -= bodySize\n\t\t\t\t\t// Set spaceReserved to false so the deferred cleanup does not unreserve again\n\t\t\t\t\tspaceReserved = false\n\t\t\t\t\tmux.Unlock()\n\t\t\t\t\treturn errors.New(\"cache: insufficient space and no entries to evict\")\n\t\t\t\t}\n\t\t\t\tnext := heap.entries[0]\n\t\t\t\tkeyToRemove, size := heap.removeFirst()\n\t\t\t\tkeysToRemove = append(keysToRemove, keyToRemove)\n\t\t\t\tsizesToRemove = append(sizesToRemove, size)\n\t\t\t\tcandidates = append(candidates, evictionCandidate{\n\t\t\t\t\tkey:  keyToRemove,\n\t\t\t\t\tsize: size,\n\t\t\t\t\texp:  next.exp,\n\t\t\t\t})\n\t\t\t\tstoredBytes -= size\n\t\t\t}\n\t\t\tmux.Unlock()\n\n\t\t\t// Perform deletions outside the lock\n\t\t\tif len(keysToRemove) > 0 {\n\t\t\t\tfor i, keyToRemove := range keysToRemove {\n\t\t\t\t\tdelErr := deleteKey(reqCtx, keyToRemove)","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/middleware/cache/cache.go#L613-L649","documentation":"Returned inline (not a sentinel var) by the cache middleware's eviction loop when MaxBytes is set, a new response body is being cached, and after reserving space for it the eviction loop has drained the entire expiration heap and storedBytes still exceeds MaxBytes. This means no remaining cached entry can be evicted to make room, so the new entry cannot be stored. The error propagates out of the cache handler and surfaces as a 500 if not otherwise handled.","triggerScenarios":"Setting cache.Config.MaxBytes to a value smaller than a single cached response body that passes the per-entry bodySize check (line 592 only rejects bodies larger than MaxBytes up front; a body just under MaxBytes still triggers this when the heap is otherwise empty). It also occurs when concurrent cache writes exhaust the heap between reservation and eviction.","commonSituations":"Setting MaxBytes very low (e.g. 1KB) while serving responses near that size; misjudging units (bytes vs KB); running under memory pressure where the cache is already full of non-expired entries; test environments with artificially tiny caches.","solutions":["Increase cache.Config.MaxBytes so it comfortably exceeds your largest cacheable response plus headroom.","If the value is correct, reduce the size of responses being cached (compression, pagination) or lower CacheExpiration so entries expire and free space.","Set MaxBytes to 0 to disable the byte budget entirely (only time-based expiration applies).","Inspect the X-Cache response header to confirm which responses are failing to cache before tuning."],"exampleFix":"// before\napp.Use(cache.New(cache.Config{\n  MaxBytes: 1024, // smaller than typical JSON responses\n}))\n// after\napp.Use(cache.New(cache.Config{\n  MaxBytes: 50 * 1024 * 1024, // 50 MB budget\n}))","handlingStrategy":"validation","validationCode":"// Validate MaxBytes vs expected response sizes at startup\nif cfg.MaxBytes > 0 && cfg.MaxBytes < maxExpectedResponse {\n    log.Printf(\"warning: cache MaxBytes (%d) smaller than largest cacheable response (%d)\", cfg.MaxBytes, maxExpectedResponse)\n}","typeGuard":null,"tryCatchPattern":"// The cache middleware returns the error from the handler; wrap your routes\napp.Use(cache.New(cfg))\napp.Use(func(c fiber.Ctx) error {\n    err := c.Next()\n    if err != nil && strings.Contains(err.Error(), \"insufficient space\") {\n        c.Set(\"X-Cache\", \"unreachable\")\n        return c.SendStatus(fiber.StatusInternalServerError)\n    }\n    return err\n})","preventionTips":["Size MaxBytes to at least 5x your largest cacheable response.","Monitor the X-Cache header to track cache effectiveness.","Set MaxBytes to 0 to rely solely on time-based expiration if byte budgeting is not needed."],"tags":["cache","configuration","memory","middleware"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}