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
- Confirm the file was produced by VoxelFileWriter (DotRecast) and the path is correct.
- Regenerate the voxel file with the current library version to clear format/version mismatch.
- 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
- Verify the file path and that it was written by VoxelFileWriter.
- Regenerate voxel files after library version upgrades.
- Check file size/hash integrity before reading.
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
- Serialization_MismatchedCount
- invalid level: {level} (expected: {LEVEL_1} or {LEVEL_2})
- 不支持导出 UnityEngine.Object 类型: {runtimeType.FullName}
- {runtimeType.FullName} 缺少可用于导出的公共构造函数。必须通过构造函数提供的成员: {names}
- 无法为类型 {type.FullName} 生成稳定排序键
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/0fd9a3c3cf66fbd4.
Report an issue: GitHub.