egametang/ET · error · Exception
Tile index too high
Error message
Tile index too high
What it means
When AddTile is called with a non-zero lastRef (restore a previously removed tile at its old slot), the decoded tile index is bounds-checked against m_maxTiles. An index at or beyond capacity means the ref did not come from this navmesh (different maxTiles, or corrupt/stale), so the restore is rejected before indexing m_tiles.
Source
Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour/DtNavMesh.cs:489
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 freelist
if (!availableTiles.Remove(target))
{
// Could not find the correct location.
throw new Exception("Could not find tile");
}
tile = target;
// Restore salt.
tile.salt = DecodePolyIdSalt(lastRef);
}
tile.data = data;
tile.flags = flags;View on GitHub (pinned to 5cab01f7a8)
Solutions
- Only pass a lastRef produced by the same DtNavMesh in its current lifetime; pass 0 for a fresh allocation when unsure.
- Do not persist refs across mesh reconfigurations; re-derive them on load.
- If streaming with restore, keep maxTiles stable across rebuilds or invalidate cached refs when it changes.
Example fix
// before: ref from another mesh / session mesh.AddTile(data, flags, persistedRef); // after: fresh allocation when the ref's provenance is uncertain mesh.AddTile(data, flags, 0);
Defensive patterns
Strategy: validation
Validate before calling
// Only restore with a ref from this mesh; otherwise allocate fresh
int idx = DecodePolyIdTile(lastRef); // helper if accessible
if (lastRef != 0 && idx >= meshMaxTiles)
throw new ArgumentOutOfRangeException(nameof(lastRef), "lastRef index exceeds mesh maxTiles");
mesh.AddTile(data, flags, provenanceUncertain ? 0 : lastRef); Try / catch
try { return mesh.AddTile(data, flags, lastRef); }
catch (Exception e) when (e.Message == "Tile index too high")
{ /* ref is foreign/stale; fall back to a fresh allocation */ return mesh.AddTile(data, flags, 0); } Prevention
- Pass lastRef only when it came from this DtNavMesh in its current lifetime.
- Do not persist refs across mesh reconfigurations.
- Keep maxTiles stable when streaming with restore, or invalidate refs on change.
When it happens
Trigger: Calling AddTile(data, flags, lastRef) with a lastRef obtained from a different DtNavMesh, a ref held across a mesh rebuild with smaller maxTiles, or a corrupted/truncated ref.
Common situations: Persisting tile refs and reloading into a mesh with different params; sharing refs between meshes; refs from a prior session whose mesh config changed.
Related errors
- Invalid tile index
- Invalid tile salt
- Tile already exists
- Item cannot be null
- MethodHook:targetMethod and replacementMethod and proxyMetho
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/690d58df915c487f.
Report an issue: GitHub.