egametang/ET · error · IOException
Invalid magic
Error message
Invalid magic
What it means
DtTileCacheLayerHeaderReader.Read parses the first two ints of a layer blob as magic and version. The magic must equal DT_TILECACHE_MAGIC ('D','T','L','R' = 0x44544C52). A mismatch means the bytes are not a tile-cache layer, or were byte-swapped relative to the reader's endianness. Thrown as IOException, so callers see it as an IO/deserialization error.
Source
Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour.TileCache/Io/DtTileCacheLayerHeaderReader.cs:35
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
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;View on GitHub (pinned to 5cab01f7a8)
Solutions
- Confirm the source is a single compressed tile-cache layer (not a set or navmesh tile).
- Make the RcByteBuffer order match the byte order used at write time; the layer reader does not auto-detect endianness.
- Re-export the layer with the current DotRecast version if it came from an incompatible producer.
Example fix
// before: wrong endianness / wrong blob type
var buf = new RcByteBuffer(bytes) { Order = RcByteOrder.BIG_ENDIAN };
var header = reader.Read(buf, cCompatibility: true);
// after: match writer order, and feed a single layer blob
var buf = new RcByteBuffer(layerBytes) { Order = writerOrder };
var header = reader.Read(buf, cCompatibility: cCompatAtWriteTime); Defensive patterns
Strategy: validation
Validate before calling
// Peek magic in the buffer's byte order before reading
int magic = buf.GetInt();
if (magic != DtTileCacheLayerHeader.DT_TILECACHE_MAGIC)
throw new InvalidDataException($"not a tile-cache layer (magic=0x{magic:X8})");
buf.Position -= 4; // rewind for the reader Try / catch
try { header = reader.Read(buf, cCompat); }
catch (IOException e) when (e.Message == "Invalid magic")
{ /* wrong blob type or wrong endianness; do not retry unchanged */ } Prevention
- Ensure the source is a single tile-cache layer, not a set or navmesh tile.
- Set the RcByteBuffer order to the writer's order; the layer reader does not auto-swap.
- Re-export layers with the current version if provenance is unclear.
When it happens
Trigger: DecompressTileCacheLayer (or direct header read) on bytes whose first int isn't DT_TILECACHE_MAGIC: wrong file type, truncated header, or endianness swapped (the reader does not auto-swap, unlike the set reader).
Common situations: Feeding a navmesh tile or a tile-cache *set* where a single layer is expected; data produced by a different tool/version; reading little-endian bytes with a big-endian RcByteBuffer.
Related errors
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/f624259d9fc14427.
Report an issue: GitHub.