egametang/ET · error · Exception

Buffer too small

Error message

Buffer too small

What it means

During monotone region partitioning of a tile-cache layer (DtTileCacheBuilder.BuildTileCacheRegions/MarkRectArea region sweep), each distinct region needs a unique id. Region ids are stored in a byte, so the partition supports at most 254 active regions; when regId reaches 255 the builder aborts with 'Buffer too small'. It means the layer's walkable spans fragment into more monotone regions than the encoding can address.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour.TileCache/DtTileCacheBuilder.cs:137

                }

                // Create unique ID.
                for (int i = 0; i < sweepId; ++i)
                {
                    // If the neighbour is set and there is only one continuous
                    // connection to it,
                    // the sweep will be merged with the previous one, else new
                    // region is created.
                    if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == sweeps[i].ns)
                    {
                        sweeps[i].id = sweeps[i].nei;
                    }
                    else
                    {
                        if (regId == 255)
                        {
                            // Region ID's overflow.
                            throw new Exception("Buffer too small");
                        }

                        sweeps[i].id = regId++;
                    }
                }

                // Remap local sweep ids to region ids.
                for (int x = 0; x < w; ++x)
                {
                    int idx = x + y * w;
                    if (layer.regs[idx] != 0xff)
                        layer.regs[idx] = (short)sweeps[layer.regs[idx]].id;
                }
            }

            // Allocate and init layer regions.
            int nregs = regId;
            DtLayerMonotoneRegion[] regs = new DtLayerMonotoneRegion[nregs];

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Reduce the tile dimensions (smaller cs/ch tileSize) so each layer holds fewer fragmented regions.
  2. Simplify collision geometry feeding the rasterizer to cut down on tiny walkable islands.
  3. Move/lower obstacle density so a single tile isn't carved into >254 regions.

Example fix

// before: large tile, dense obstacles
var cp = new DtTileCacheParams { width = 256, height = 256, ch = 0.2f, cs = 0.3f, ... };

// after: smaller tile per layer reduces region fragmentation
var cp = new DtTileCacheParams { width = 128, height = 128, ch = 0.2f, cs = 0.3f, ... };
Defensive patterns

Strategy: validation

Validate before calling

// Heuristic guard before building a tile-cache layer:
// keep per-tile walkable fragmentation well under 254 regions.
// Validate tile size vs geometry density in your bake config.
if (tileWidth * tileHeight > MaxCellsPerTile)
    throw new InvalidOperationException(
        "Tile too large/dense; reduce tileSize or cs to keep monotone regions < 255.");

Try / catch

try { cache.BuildNavMeshTile(ref); }
catch (Exception e) when (e.Message == "Buffer too small")
{ /* re-bake this tile smaller or simplify its geometry */ }

Prevention

When it happens

Trigger: Building a tile-cache layer whose walkable area is highly fragmented: many disjoint walkable islands, thin corridors, or heavy obstacle carving within one tile. Triggered by DtTileCache.BuildNavMeshTile -> builder region step on such a layer.

Common situations: Tile size too large relative to geometry complexity; many small obstacles carved into a single tile; noisy heightfield with many isolated ledges; cell size too coarse creating fragmentation.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/87f4a90830782f72. Report an issue: GitHub.