Perfare/Il2CppDumper · error · NotSupportedException
Invalid Optional header magic
Error message
Invalid Optional header magic {magic} What it means
Thrown during PE header parsing after the PE signature and COFF FileHeader have been read. The first UInt16 of the Optional Header (the magic) determines whether the image is PE32 (0x10b, 32-bit, parsed with OptionalHeader) or PE32+ (0x20b, 64-bit, parsed with OptionalHeader64). Any other value means the file is not a valid PE executable — it may be corrupted, truncated, or an entirely different format misidentified as PE — so the parser cannot determine the image bitness or locate the ImageBase and aborts by raising this NotSupportedException at Il2CppDumper/ExecutableFormats/PE.cs:41. The faulting input is the Optional Header magic field of the loaded file.
Solutions
- Confirm the binary is a standard PE32 (magic 0x10b) or PE32+ (magic 0x20b) using a tool like CFF Explorer or pestudio.
- Re-obtain the original GameAssembly.dll without post-processing/packing that alters headers.
- If the file is a console/custom PE variant, this dumper does not support it; use a platform-specific extraction tool first.
- Verify the file hash against the original build output to rule out corruption.
Example fix
// before // magic read as 0x020C (ROM image) -> NotSupportedException // after // supply a standard PE: check bytes at PE offset + 24 == 0x0B01 or 0x0B02 (LE)
Defensive patterns
Strategy: validation
Validate before calling
byte[] b = File.ReadAllBytes(path); uint off = BitConverter.ToUInt32(b, 0x3C); ushort magic = BitConverter.ToUInt16(b, (int)off + 24); bool ok = magic == 0x10b || magic == 0x20b; // PE32 or PE32+
Type guard
static bool IsStandardPeOptionalHeader(byte[] b) { uint o = BitConverter.ToUInt32(b, 0x3C); ushort m = BitConverter.ToUInt16(b, (int)o + 24); return m is 0x10b or 0x20b; } Try / catch
try { var pe = new PE(stream); }
catch (NotSupportedException ex) when (ex.Message.StartsWith("Invalid Optional header magic")) { /* unsupported PE variant */ } Prevention
- Confirm with a PE editor that the optional header magic is 0x10b or 0x20b.
- Avoid packed/protected builds that mangle optional headers; unpack first.
- Keep the original unmodified GameAssembly.dll from the build output.
When it happens
Trigger: Calling new PE(stream) on a PE whose optional header magic read at FileHeader end is not 0x10b or 0x20b — e.g. ROM images, unknown/corrupt optional headers, or files where SizeOfOptionalHeader/magic got mangled.
Common situations: Dumping non-standard PE derivatives (Xbox/UWP custom headers), files hand-edited or corrupted in transit, or obfuscated/packed binaries that scrambled the optional header.
Related errors
AI-assisted analysis of Perfare/Il2CppDumper@4741d46ba9 (2026-09-11).
Data as JSON: /api/errors/fabd444ecb860f60.
Report an issue: GitHub.
Appendix: source
Thrown at Il2CppDumper/ExecutableFormats/PE.cs:41
}
var fileHeader = ReadClass<FileHeader>();
var pos = Position;
var magic = ReadUInt16();
Position -= 2;
if (magic == 0x10b)
{
Is32Bit = true;
var optionalHeader = ReadClass<OptionalHeader>();
ImageBase = optionalHeader.ImageBase;
}
else if (magic == 0x20b)
{
var optionalHeader = ReadClass<OptionalHeader64>();
ImageBase = optionalHeader.ImageBase;
}
else
{
throw new NotSupportedException($"Invalid Optional header magic {magic}");
}
Position = pos + fileHeader.SizeOfOptionalHeader;
sections = ReadClassArray<SectionHeader>(fileHeader.NumberOfSections);
}
public void LoadFromMemory(ulong addr)
{
ImageBase = addr;
foreach (var section in sections)
{
section.PointerToRawData = section.VirtualAddress;
section.SizeOfRawData = section.VirtualSize;
}
}
public override ulong MapVATR(ulong absAddr)
{
var addr = absAddr - ImageBase;View on GitHub (pinned to 4741d46ba9)