icsharpcode/ILSpy · error · BadImageFormatException
Invalid metadata token
Error message
Invalid metadata token
What it means
BadImageFormatException thrown by ReadAndDecodeMetadataToken when the 4-byte token read from the IL stream is <= 0. SRM (System.Reflection.Metadata) uses negative integers as 'virtual tokens' and gets confused if one is fabricated, and row ids below 1 are never valid, so a non-positive token signals a corrupted or truncated method body.
Source
Thrown at ICSharpCode.Decompiler/IL/ILReader.cs:223
v.InitialValueIsInitialized = body.LocalVariablesInitialized;
v.UsesInitialValue = true;
}
this.mainContainer = new BlockContainer(expectedResultType: methodReturnStackType);
this.blocksByOffset.Clear();
this.importQueue.Clear();
this.isBranchTarget = new BitSet(reader.Length);
this.variableByExceptionHandler.Clear();
}
EntityHandle ReadAndDecodeMetadataToken()
{
int token = reader.ReadInt32();
if (token <= 0)
{
// SRM uses negative tokens as "virtual tokens" and can get confused
// if we manually create them.
// Row-IDs < 1 are always invalid.
throw new BadImageFormatException("Invalid metadata token");
}
var handle = MetadataTokens.EntityHandle(token);
if (handle.IsNil)
{
// The runtime will crash with a BadImageFormatException when it encounters a row-ID of 0.
// We assume the code following this instruction to be unreachable.
throw new BadImageFormatException("Invalid metadata token");
}
return handle;
}
IType ReadAndDecodeTypeReference()
{
var typeReference = ReadAndDecodeMetadataToken();
return module.ResolveType(typeReference, genericContext);
}
IMethod ReadAndDecodeMethodReference()
View on GitHub (pinned to 60c08fcb74)
Solutions
- Treat the assembly as untrusted input and wrap decompilation in try/catch for BadImageFormatException.
- Verify the file is a valid managed PE before decompiling (e.g. PEReader.IsEntireImageAvailable / check the PE header).
- Re-acquire a clean copy of the assembly if the stream is truncated.
Example fix
// before
var result = decompiler.DecompileAssembly(assemblyPath);
// after
try
{
var result = decompiler.DecompileAssembly(assemblyPath);
}
catch (BadImageFormatException ex)
{
logger.Warn($"Corrupt assembly {assemblyPath}: {ex.Message}");
} Defensive patterns
Strategy: try-catch
Validate before calling
bool IsValidPe(string path)
{
try { using var pe = new PEReader(File.OpenRead(path)); return pe.PEHeaders != null; }
catch { return false; }
} Try / catch
try { var code = decompiler.DecompileTypeAsString(typeName); }
catch (BadImageFormatException ex) { logger.Warn($"Corrupt IL in {assemblyPath}: {ex.Message}"); } Prevention
- Treat decompiled assemblies as untrusted input and catch BadImageFormatException.
- Validate the PE header before decompiling when you preprocess inputs.
- Re-download a clean copy when a stream looks truncated.
When it happens
Trigger: Decompiling an assembly whose IL stream contains a garbage/negative token operand: truncated method body, hand-crafted malformed IL, or an obfuscated binary with tampered token bytes.
Common situations: Obfuscated or packed assemblies; assemblies corrupted on disk or in transit; IL emitted by a buggy/illicit code generator writing invalid token operands.
Related errors
AI-assisted analysis of icsharpcode/ILSpy@60c08fcb74 (2026-08-13).
Data as JSON: /api/errors/f2674c73c705e025.
Report an issue: GitHub.