egametang/ET · error · IOException
Invalid version {header.version}
Error message
Invalid version {header.version} What it means
Thrown by DtMeshDataReader.Read when the mesh header version falls outside the supported recast4j range [DT_NAVMESH_VERSION_RECAST4J_FIRST, DT_NAVMESH_VERSION_RECAST4J_LAST] and is not the current DT_NAVMESH_VERSION. The file was written by a Detour/recast4j version this reader cannot interpret.
Source
Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour/Io/DtMeshDataReader.cs:73
header.magic = buf.GetInt();
if (header.magic != DtMeshHeader.DT_NAVMESH_MAGIC)
{
header.magic = IOUtils.SwapEndianness(header.magic);
if (header.magic != DtMeshHeader.DT_NAVMESH_MAGIC)
{
throw new IOException("Invalid magic");
}
buf.Order(buf.Order() == RcByteOrder.BIG_ENDIAN ? RcByteOrder.LITTLE_ENDIAN : RcByteOrder.BIG_ENDIAN);
}
header.version = buf.GetInt();
if (header.version != DtMeshHeader.DT_NAVMESH_VERSION)
{
if (header.version < DtMeshHeader.DT_NAVMESH_VERSION_RECAST4J_FIRST
|| header.version > DtMeshHeader.DT_NAVMESH_VERSION_RECAST4J_LAST)
{
throw new IOException("Invalid version " + header.version);
}
}
bool cCompatibility = header.version == DtMeshHeader.DT_NAVMESH_VERSION;
header.x = buf.GetInt();
header.y = buf.GetInt();
header.layer = buf.GetInt();
header.userId = buf.GetInt();
header.polyCount = buf.GetInt();
header.vertCount = buf.GetInt();
header.maxLinkCount = buf.GetInt();
header.detailMeshCount = buf.GetInt();
header.detailVertCount = buf.GetInt();
header.detailTriCount = buf.GetInt();
header.bvNodeCount = buf.GetInt();
header.offMeshConCount = buf.GetInt();
header.offMeshBase = buf.GetInt();
header.walkableHeight = buf.GetFloat();View on GitHub (pinned to 5cab01f7a8)
Solutions
- Re-bake/re-export navmesh data with the same DotRecast version the runtime uses.
- Pin the asset-producing tool and the runtime to a compatible Detour version.
- Check DtMeshHeader.DT_NAVMESH_VERSION against the version in the file before loading.
Example fix
// before var data = meshDataReader.Read(buf, nvp, is32Bit); // throws on old asset // after // re-export asset with current toolchain, then: var data = meshDataReader.Read(buf, nvp, is32Bit);
Defensive patterns
Strategy: validation
Validate before calling
int v = BitConverter.ToInt32(chunk, 4);
bool ok = v == DtMeshHeader.DT_NAVMESH_VERSION ||
(v >= DtMeshHeader.DT_NAVMESH_VERSION_RECAST4J_FIRST &&
v <= DtMeshHeader.DT_NAVMESH_VERSION_RECAST4J_LAST);
if (!ok) throw new InvalidDataException($"Unsupported mesh version {v}"); Type guard
static bool IsSupportedMeshVersion(int v)
=> v == DtMeshHeader.DT_NAVMESH_VERSION ||
(v >= DtMeshHeader.DT_NAVMESH_VERSION_RECAST4J_FIRST &&
v <= DtMeshHeader.DT_NAVMESH_VERSION_RECAST4J_LAST); Try / catch
try { var data = meshDataReader.Read(buf, nvp, is32Bit); }
catch (IOException e) when (e.Message.Contains("Invalid version"))
{ /* re-bake asset with matching toolchain */ } Prevention
- Keep the bake toolchain and runtime on the same Detour version.
- Re-bake navmesh assets after package upgrades.
- Version-check the header before loading.
When it happens
Trigger: Loading a tile mesh generated by a newer or older recast4j/DotRecast build than the runtime library; mixing outputs from different Detour forks.
Common situations: Updating the DotRecast package version after baking navmesh assets with the old version; consuming assets produced by a different Detour implementation.
Related errors
- Invalid version {header.version}
- Invalid magic
- Invalid number of verts per poly {header.maxVertsPerPoly}
- Invalid magic {header.magic}
- Invalid version
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/3f7e8d3c054dbf1c.
Report an issue: GitHub.