egametang/ET · error · IOException

Invalid magic

Error message

Invalid magic

What it means

VoxelFileReader.Read validates the first 4 bytes (magic number) of a voxel file against VoxelFile.MAGIC, trying both endianness. If neither matches, the stream is not a valid DotRecast/Detour voxel file. This guards against feeding corrupt or foreign-format data to the dynamic navmesh voxel loader.

Source

Thrown at Packages/cn.etetet.recast/Scripts/Core/Share/Detour.Dynamic/Io/VoxelFileReader.cs:45

    {
        private readonly IRcCompressor _compressor;

        public VoxelFileReader(IRcCompressor compressor)
        {
            _compressor = compressor;
        }

        public VoxelFile Read(BinaryReader stream)
        {
            RcByteBuffer buf = IOUtils.ToByteBuffer(stream);
            VoxelFile file = new VoxelFile();
            int magic = buf.GetInt();
            if (magic != VoxelFile.MAGIC)
            {
                magic = IOUtils.SwapEndianness(magic);
                if (magic != VoxelFile.MAGIC)
                {
                    throw new IOException("Invalid magic");
                }

                buf.Order(buf.Order() == RcByteOrder.BIG_ENDIAN ? RcByteOrder.LITTLE_ENDIAN : RcByteOrder.BIG_ENDIAN);
            }

            file.version = buf.GetInt();
            bool isExportedFromAstar = (file.version & VoxelFile.VERSION_EXPORTER_MASK) == 0;
            bool compression = (file.version & VoxelFile.VERSION_COMPRESSION_MASK) == VoxelFile.VERSION_COMPRESSION_LZ4;
            file.walkableRadius = buf.GetFloat();
            file.walkableHeight = buf.GetFloat();
            file.walkableClimb = buf.GetFloat();
            file.walkableSlopeAngle = buf.GetFloat();
            file.cellSize = buf.GetFloat();
            file.maxSimplificationError = buf.GetFloat();
            file.maxEdgeLen = buf.GetFloat();
            file.minRegionArea = (int)buf.GetFloat();
            if (!isExportedFromAstar)
            {

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Confirm the file was produced by VoxelFileWriter (DotRecast) and the path is correct.
  2. Regenerate the voxel file with the current library version to clear format/version mismatch.
  3. Verify file integrity (size, hash) before reading; handle IOException and re-export on failure.

Example fix

// before
var file = new VoxelFileReader(compressor).Read(new BinaryReader(File.OpenRead(path)));

// after — guard format
using var fs = File.OpenRead(path);
using var br = new BinaryReader(fs);
try { return new VoxelFileReader(compressor).Read(br); }
catch (IOException) { Log.Error($"{path} is not a valid voxel file, regenerating"); return Regenerate(path); }
Defensive patterns

Strategy: try-catch

Try / catch

try { return new VoxelFileReader(compressor).Read(br); }
catch (IOException) { Log.Error($"{path} is not a valid voxel file"); return Regenerate(path); }

Prevention

When it happens

Trigger: Opening a file that is not a voxel file at all (e.g. a navmesh .bin, a text file, a truncated file); a voxel file from an incompatible DotRecast/recast4j version with a different magic; a file whose header was overwritten/corrupted.

Common situations: Wrong file path passed to the reader; cached voxel file from an older library version; file download/copy was interrupted leaving a partial/corrupt header.

Related errors


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