icsharpcode/ILSpy · error · ArgumentException

The handle must not be nil.

Error message

The handle must not be nil.

What it means

ArgumentException thrown by the GetIdString(MetadataFile, EntityHandle) worker when the supplied EntityHandle is nil (row id 0). XML doc ID strings describe exactly one concrete metadata entity, and a nil handle encodes 'no entity', so the worker refuses it. The public GetIdString(this IEntity) path already pre-checks entity.MetadataToken.IsNil, so reaching this throw means a caller invoked the handle-based overload directly and bypassed that guard.

Source

Thrown at ICSharpCode.Decompiler/Documentation/IdStringProvider.cs:134

							|| !metadata.StringComparer.Equals(metadata.GetPropertyDefinition(sibling).Name, name))
						{
							continue;
						}
						if (GetIdString(module, sibling, cppCliDialect: true) == roslynForm)
							return true;
					}
					return false;
				}

				default:
					return false;
			}
		}

		static string GetIdString(MetadataFile module, EntityHandle handle, bool cppCliDialect)
		{
			if (handle.IsNil)
				throw new ArgumentException("The handle must not be nil.", nameof(handle));

			var metadata = module.Metadata;
			var b = new StringBuilder();

			switch (handle.Kind)
			{
				case HandleKind.TypeDefinition:
					b.Append("T:");
					AppendTypeDefinitionName(b, metadata, (TypeDefinitionHandle)handle);
					break;

				case HandleKind.FieldDefinition:
					b.Append("F:");
					AppendFieldIdString(b, metadata, (FieldDefinitionHandle)handle);
					break;

				case HandleKind.MethodDefinition:
					b.Append("M:");

View on GitHub (pinned to 60c08fcb74)

Solutions

  1. Check handle.IsNil before calling GetIdString and skip nil handles.
  2. Prefer the GetIdString(this IEntity entity) overload, which already guards nil tokens and non-metadata entities.
  3. When iterating handles, filter early: `if (handle.IsNil) continue;`.

Example fix

// before
foreach (var h in handles)
    idStrings.Add(IdStringProvider.GetIdString(module, h));

// after
foreach (var h in handles)
{
    if (h.IsNil) continue;
    idStrings.Add(IdStringProvider.GetIdString(module, h));
}
Defensive patterns

Strategy: validation

Validate before calling

if (handle.IsNil) return null; // or continue / skip
var id = IdStringProvider.GetIdString(module, handle);

Type guard

static bool IsComputableHandle(EntityHandle h) => !h.IsNil && h.Kind is HandleKind.TypeDefinition or HandleKind.FieldDefinition or HandleKind.MethodDefinition or HandleKind.PropertyDefinition or HandleKind.EventDefinition;

Prevention

When it happens

Trigger: Calling GetIdString(module, handle) with a handle obtained from a source that can yield nil: typeDef.GetDeclaringType() on a top-level type, a property/event's declaring-type lookup, or entity.MetadataToken on an entity that is not metadata-backed, without an IsNil guard.

Common situations: Iterating every member/type in a table and feeding each handle to GetIdString; resolving the declaring type of properties or events (which can be nil for edge cases); converting a handle that came from a lookup that may not have matched anything.

Related errors


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