icsharpcode/ILSpy · error · BadImageFormatException

Invalid field token

Error message

Invalid field token

What it means

BadImageFormatException thrown by ReadAndDecodeFieldReference when the operand token of a field instruction (ldfld/ldsfld/stfld/ldflda) resolved to an entity that is not an IField. Field instructions must reference a field; resolving their token to a method, type, or other entity means the token's table bits or row do not describe a field.

Source

Thrown at ICSharpCode.Decompiler/IL/ILReader.cs:252

		IType ReadAndDecodeTypeReference()
		{
			var typeReference = ReadAndDecodeMetadataToken();
			return module.ResolveType(typeReference, genericContext);
		}

		IMethod ReadAndDecodeMethodReference()
		{
			var methodReference = ReadAndDecodeMetadataToken();
			return module.ResolveMethod(methodReference, genericContext);
		}

		IField ReadAndDecodeFieldReference()
		{
			var fieldReference = ReadAndDecodeMetadataToken();
			var f = module.ResolveEntity(fieldReference, genericContext) as IField;
			if (f == null)
				throw new BadImageFormatException("Invalid field token");
			return f;
		}

		ILVariable[] InitLocalVariables()
		{
			if (body.LocalSignature.IsNil)
				return Empty<ILVariable>.Array;
			ImmutableArray<IType> variableTypes;
			try
			{
				variableTypes = module.DecodeLocalSignature(body.LocalSignature, genericContext);
			}
			catch (BadImageFormatException ex)
			{
				Warnings.Add("Error decoding local variables: " + ex.Message);
				variableTypes = ImmutableArray<IType>.Empty;
			}
			var localVariables = new ILVariable[variableTypes.Length];

View on GitHub (pinned to 60c08fcb74)

Solutions

  1. Catch BadImageFormatException around decompilation and treat the assembly/method as unreadable.
  2. Use a metadata reader to cross-check that field tokens actually point at FieldDefinition rows before decompiling.
  3. Obtain an unobfuscated or uncorrupted copy of the binary.

Example fix

// before
var code = decompiler.DecompileTypeAsString(typeName);

// after
try
{
    var code = decompiler.DecompileTypeAsString(typeName);
}
catch (BadImageFormatException ex) when (ex.Message.Contains("field token"))
{
    logger.Warn($"Field token corruption in {typeName}: {ex.Message}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

void VerifyFieldTokens(string path)
{
    using var pe = new PEReader(File.OpenRead(path));
    var md = pe.GetMetadataReader();
    foreach (var h in md.MethodDefinitions)
    {
        var body = pe.GetMethodBody(md.GetMethodDefinition(h).RelativeVirtualAddress);
        // token table byte (>>24) for field ops should be 0x04 (FieldDef) in valid IL
    }
}

Try / catch

try { var code = decompiler.DecompileTypeAsString(typeName); }
catch (BadImageFormatException ex) when (ex.Message.Contains("field token")) { logger.Warn($"Field token corruption: {ex.Message}"); }

Prevention

When it happens

Trigger: A field-instruction operand token whose table type is wrong (points at a MethodDef/TypeDef) or whose row is mismatched; produced by corrupt metadata or an obfuscator that rewrites token tables.

Common situations: Obfuscated assemblies that swap token tables; assemblies damaged by tooling that rewrote the metadata stream; manually edited IL.

Related errors


AI-assisted analysis of icsharpcode/ILSpy@60c08fcb74 (2026-08-13). Data as JSON: /api/errors/4633c519373c6f71. Report an issue: GitHub.