egametang/ET · error · Exception
Could not allocate a tile
Error message
Could not allocate a tile
What it means
DtNavMesh.AddTile with lastRef == 0 allocates a fresh tile from the free-list (availableTiles). When the list is empty, all m_maxTiles slots are in use and no tile can be assigned; the add fails. This is a capacity limit on the DtNavMesh, set at construction via the mesh params maxTiles.
Source
Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour/DtNavMesh.cs:476
public long AddTile(DtMeshData data, int flags, long lastRef)
{
// Make sure the data is in right format.
DtMeshHeader header = data.header;
// Make sure the location is free.
if (GetTileAt(header.x, header.y, header.layer) != null)
{
throw new Exception("Tile already exists");
}
// Allocate a tile.
DtMeshTile tile = null;
if (lastRef == 0)
{
// Make sure we could allocate a tile.
if (0 == availableTiles.Count)
{
throw new Exception("Could not allocate a tile");
}
tile = availableTiles.First?.Value;
availableTiles.RemoveFirst();
m_tileCount++;
}
else
{
// Try to relocate the tile to specific index with same salt.
int tileIndex = DecodePolyIdTile(lastRef);
if (tileIndex >= m_maxTiles)
{
throw new Exception("Tile index too high");
}
// Try to find the specific tile id from the free list.
DtMeshTile target = m_tiles[tileIndex];
// Remove from freelistView on GitHub (pinned to 5cab01f7a8)
Solutions
- Increase the DtNavMesh maxTiles (passed at DtNavMesh construction) above peak live tile count.
- Ensure RemoveTile is called on unload so slots return to the free-list.
- Track live tile count and shed/defer loads when near capacity.
Example fix
// before: mesh built with too few tiles
var mesh = new DtNavMesh(new DtNavMeshParams { ... maxTiles = 512 });
foreach (var d in allData) mesh.AddTile(d, 0, 0); // overflows
// after: size to peak, and remove before re-adding
var mesh = new DtNavMesh(new DtNavMeshParams { ... maxTiles = 4096 }); Defensive patterns
Strategy: validation
Validate before calling
if (mesh.GetTileCount() >= meshMaxTiles)
throw new InvalidOperationException(
$"DtNavMesh at capacity ({mesh.GetTileCount()}/{meshMaxTiles}); remove a tile or raise maxTiles.");
mesh.AddTile(data, flags, 0); Try / catch
try { return mesh.AddTile(data, flags, 0); }
catch (Exception e) when (e.Message == "Could not allocate a tile")
{ /* evict a tile, then retry once, or report capacity */ } Prevention
- Size DtNavMesh maxTiles above peak live tile count.
- Always pair AddTile with RemoveTile.
- Track live count and defer loads when near capacity.
When it happens
Trigger: Calling AddTile(data, flags, 0) more than maxTiles times without matching RemoveTile; loading a navmesh whose tile count exceeds the mesh's configured maxTiles.
Common situations: maxTiles sized too small for the world; tiles added but never removed on unload; streaming that exceeds the pre-allocated slot count at peak.
Related errors
- Out of storage
- ERR_LocationLockOwnerMismatch
- btenv not found key: {key} {typeof(T).FullName}
- 不能把{value.GetType()}转换为{typeof (T)}
- condition root child count error: {node.Children.Count}
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/4d765601b4772fd1.
Report an issue: GitHub.