icsharpcode/ILSpy · error · ArgumentException

types contains null element

Error message

types contains null element

What it means

Thrown by DecompileTypes(IEnumerable<TypeDefinitionHandle>) when the input sequence contains a handle whose IsNil is true. A nil TypeDefinitionHandle is the default/zero value of the metadata-handle struct (token 0), which points at no row in the TypeDef table. The library rejects it because there is no type to decompile, and silently skipping would hide a caller bug.

Source

Thrown at ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs:1299

		/// <summary>
		/// Decompile the given types.
		/// </summary>
		/// <remarks>
		/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definitions.
		/// </remarks>
		public SyntaxTree DecompileTypes(IEnumerable<TypeDefinitionHandle> types)
		{
			if (types == null)
				throw new ArgumentNullException(nameof(types));
			var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
			syntaxTree = new SyntaxTree();
			var namespaces = new HashSet<string>();
			foreach (var type in types)
			{
				CancellationToken.ThrowIfCancellationRequested();
				if (type.IsNil)
					throw new ArgumentException("types contains null element");
				RequiredNamespaceCollector.CollectNamespaces(type, module, namespaces);
			}

			var decompileRun = CreateDecompileRun(namespaces);
			DoDecompileTypes(types, decompileRun, decompilationContext, syntaxTree);
			RunTransforms(syntaxTree, decompileRun, decompilationContext);
			return syntaxTree;
		}

		/// <summary>
		/// Decompile the given types.
		/// </summary>
		/// <remarks>
		/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definitions.
		/// </remarks>
		public string DecompileTypesAsString(IEnumerable<TypeDefinitionHandle> types)
		{
			return SyntaxTreeToString(DecompileTypes(types));

View on GitHub (pinned to 60c08fcb74)

Solutions

  1. Filter the handle list to exclude nil entries before calling: types.Where(h => !h.IsNil).
  2. When building the list from row indices, skip index 0 and any entry whose GetToken() == 0.
  3. Guard the collection up front: if (types.Any(t => t.IsNil)) throw your own ArgumentException with caller context.

Example fix

// before
var handles = metadata.TypeDefinitions.Where(h => Matches(h)).ToList();
var tree = decompiler.DecompileTypes(handles);

// after
var handles = metadata.TypeDefinitions.Where(h => Matches(h) && !h.IsNil).ToList();
if (handles.Count == 0) return;
var tree = decompiler.DecompileTypes(handles);
Defensive patterns

Strategy: validation

Validate before calling

var valid = types.Where(h => !h.IsNil).ToList();
if (valid.Count == 0) return;
var tree = decompiler.DecompileTypes(valid);

Type guard

static bool IsValidTypeHandle(TypeDefinitionHandle h) => !h.IsNil;

Prevention

When it happens

Trigger: Calling DecompileTypes with a collection that includes default(TypeDefinitionHandle) or MetadataTokens.TypeDefinitionHandle(0). Usually a LINQ/filter step that produced a nil entry for a missing row, an uninitialized array slot, or an off-by-one handle computation.

Common situations: Handles taken from a dictionary/lookup that returns default on miss; arrays allocated larger than the data they hold; translating row indices where a missing row maps to 0.

Related errors


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