{"record":{"id":"5df43a91d2664a84","repo":"egametang/ET","slug":"out-of-storage","errorCode":null,"errorMessage":"Out of storage","messagePattern":"Out of storage","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"Packages/cn.etetet.recast/Scripts/Core/Share/Detour.TileCache/DtTileCache.cs","lineNumber":264,"sourceCode":"            // Make sure the location is free.\n            if (GetTileAt(header.tx, header.ty, header.tlayer) != null)\n            {\n                return 0;\n            }\n\n            // Allocate a tile.\n            DtCompressedTile tile = null;\n            if (m_nextFreeTile != null)\n            {\n                tile = m_nextFreeTile;\n                m_nextFreeTile = tile.next;\n                tile.next = null;\n            }\n\n            // Make sure we could allocate a tile.\n            if (tile == null)\n            {\n                throw new Exception(\"Out of storage\");\n            }\n\n            // Insert tile into the position lut.\n            int h = DtNavMesh.ComputeTileHash(header.tx, header.ty, m_tileLutMask);\n            tile.next = m_posLookup[h];\n            m_posLookup[h] = tile;\n\n            // Init tile.\n            tile.header = header;\n            tile.data = data;\n            tile.compressed = Align4(buf.Position());\n            tile.flags = flags;\n\n            return GetTileRef(tile);\n        }\n\n        private int Align4(int i)\n        {","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.recast/Scripts/Core/Share/Detour.TileCache/DtTileCache.cs#L246-L282","documentation":"Thrown by DtTileCache.AddTile when the free-list of compressed tiles (m_nextFreeTile) is empty. The cache pre-allocates exactly maxTiles slots at construction and hands them out as tiles are added; once all are in use, no slot can be assigned and the add fails. It indicates the cache is at capacity, not a memory allocation failure.","triggerScenarios":"Calling DtTileCache.AddTile(...) more than DtTileCacheParams.maxTiles times without matching RemoveTile calls; loading a tile set whose tile count exceeds the configured maxTiles; streaming new tiles while old ones are never evicted.","commonSituations":"maxTiles sized too small for the streamed world; obstacle/tile updates queuing many tiles before the update loop drains them; a tile loaded twice because RemoveTile was skipped on unload; mismatch between the maxTiles the cache was built with and the tile count the loader assumes.","solutions":["Increase DtTileCacheParams.maxTiles to exceed the peak number of simultaneously live tiles (including obstacle-driven rebuilds).","Ensure every load path has a matching RemoveTile on unload so the free-list is replenished.","Drive DtTileCache.Update each frame so pending add/remove requests settle before the next batch of AddTile calls."],"exampleFix":"// before: add without ever removing\nforeach (var data in loaded) cache.AddTile(data, flags, 0);\n\n// after: remove the tile at the same (tx,ty,layer) before re-adding, and size maxTiles to peak load\nlong oldRef = cache.GetTileRef(tx, ty, layer);\nif (oldRef != 0) cache.RemoveTile(oldRef);\ncache.AddTile(data, flags, 0);","handlingStrategy":"validation","validationCode":"// Track live tile count against capacity before adding\nif (liveTileCount >= cacheMaxTiles)\n    throw new InvalidOperationException(\n        $\"DtTileCache at capacity ({liveTileCount}/{cacheMaxTiles}); \" +\n        \"remove a tile or raise maxTiles.\");\ncache.AddTile(data, flags, 0);","typeGuard":null,"tryCatchPattern":"try { return cache.AddTile(data, flags, 0); }\ncatch (Exception e) when (e.Message == \"Out of storage\")\n{ /* evict least-recent tile, then retry once, or report capacity */ }","preventionTips":["Size maxTiles to peak concurrent tiles including obstacle rebuilds.","Always pair AddTile with RemoveTile on unload.","Call DtTileCache.Update each frame so pending requests settle."],"tags":["capacity","detour-tilecache","runtime"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}