egametang/ET · error · IOException

Invalid version

Error message

Invalid version

What it means

After the magic check passes, DtTileCacheLayerHeaderReader.Read verifies the version int equals DT_TILECACHE_VERSION (currently 1). A different version means the layer was written by an incompatible (newer or older) format that this reader cannot parse safely. Thrown as IOException.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour.TileCache/Io/DtTileCacheLayerHeaderReader.cs:37

*/

using System.IO;
using DotRecast.Core;

namespace DotRecast.Detour.TileCache.Io
{
    public class DtTileCacheLayerHeaderReader
    {
        public DtTileCacheLayerHeader Read(RcByteBuffer data, bool cCompatibility)
        {
            DtTileCacheLayerHeader header = new DtTileCacheLayerHeader();
            header.magic = data.GetInt();
            header.version = data.GetInt();

            if (header.magic != DtTileCacheLayerHeader.DT_TILECACHE_MAGIC)
                throw new IOException("Invalid magic");
            if (header.version != DtTileCacheLayerHeader.DT_TILECACHE_VERSION)
                throw new IOException("Invalid version");

            header.tx = data.GetInt();
            header.ty = data.GetInt();
            header.tlayer = data.GetInt();
            
            header.bmin.x = data.GetFloat();
            header.bmin.y = data.GetFloat();
            header.bmin.z = data.GetFloat();
            header.bmax.x = data.GetFloat();
            header.bmax.y = data.GetFloat();
            header.bmax.z = data.GetFloat();

            header.hmin = data.GetShort() & 0xFFFF;
            header.hmax = data.GetShort() & 0xFFFF;
            header.width = data.Get() & 0xFF;
            header.height = data.Get() & 0xFF;
            header.minx = data.Get() & 0xFF;
            header.maxx = data.Get() & 0xFF;

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Re-bake/re-export the tile-cache layers with the DotRecast version that will load them.
  2. Pin producer and consumer to the same DotRecast version in your asset pipeline.
  3. If you must migrate, write a one-time converter that reads the old version and writes the current one.

Example fix

// before: layers baked on DotRecast 1.x loaded by 2.x
var layer = builder.DecompressTileCacheLayer(comp, oldBytes, order, cCompat);

// after: re-bake with the consuming version (or run a migration converter)
// re-export layers so header.version == DtTileCacheLayerHeader.DT_TILECACHE_VERSION
Defensive patterns

Strategy: try-catch

Validate before calling

int v = buf.GetInt(); // after magic
if (v != DtTileCacheLayerHeader.DT_TILECACHE_VERSION)
    throw new InvalidDataException($"unsupported layer version {v} (expected {DtTileCacheLayerHeader.DT_TILECACHE_VERSION})");

Try / catch

try { header = reader.Read(buf, cCompat); }
catch (IOException e) when (e.Message == "Invalid version")
{ /* re-bake layer with the current DotRecast version */ }

Prevention

When it happens

Trigger: Reading a tile-cache layer produced by a different DotRecast/recast4j version whose DT_TILECACHE_VERSION differs; partially overwritten bytes where the version int is corrupt after a valid magic.

Common situations: Upgrading DotRecast across a version bump that changed the layer format; loading caches baked on another toolchain/version; cross-version asset pipelines.

Related errors


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