AvaloniaUI/Avalonia · error · ArgumentException

Unexpected null returned from Type.GetTypeFromHandle in Meth

Error message

Unexpected null returned from Type.GetTypeFromHandle in MethodAsDelegateElement

What it means

Thrown as ArgumentException by the MethodAsDelegateElement constructor when Type.GetTypeFromHandle(delegateType) returns null. A RuntimeTypeHandle must correspond to a loaded Type; a null result means the handle is invalid, zero, or refers to a type in an unloaded assembly.

Source

Thrown at src/Avalonia.Base/Data/CompiledBindingPath.cs:277

        public Func<WeakReference<object?>, IPropertyInfo, IPropertyAccessor> AccessorFactory { get; }

        public bool AcceptsNull { get; }

        public override string ToString()
            => _isFirstElement ? Property.Name : $".{Property.Name}";
    }

    internal class MethodAsDelegateElement : ICompiledBindingPathElement
    {
        public MethodAsDelegateElement(
            RuntimeMethodHandle method,
            RuntimeTypeHandle delegateType,
            bool acceptsNull)
        {
            Method = MethodBase.GetMethodFromHandle(method) as MethodInfo
                ?? throw new ArgumentException("Invalid method handle", nameof(method));
            DelegateType = Type.GetTypeFromHandle(delegateType)
                ?? throw new ArgumentException("Unexpected null returned from Type.GetTypeFromHandle in MethodAsDelegateElement");
            AcceptsNull = acceptsNull;
        }

        public MethodInfo Method { get; }

        public Type DelegateType { get; }

        public bool AcceptsNull { get; }
    }

    internal class MethodAsCommandElement : ICompiledBindingPathElement
    {
        public MethodAsCommandElement(string methodName, Action<object, object?> executeHelper, Func<object, object?, bool>? canExecuteHelper, string[] dependsOnElements)
        {
            MethodName = methodName;
            ExecuteMethod = executeHelper;
            CanExecuteMethod = canExecuteHelper;
            DependsOnProperties = new HashSet<string>(dependsOnElements);

View on GitHub (pinned to 11c5427268)

Solutions

  1. Obtain the RuntimeTypeHandle from a live loaded Type via typeof(T).TypeHandle or type.TypeHandle, never default.
  2. In trimming/AOT scenarios, ensure the delegate type is rooted/preserved so its handle resolves at runtime.
  3. Validate Type.GetTypeFromHandle(delegateType) != null before passing to the builder.

Example fix

// before
builder.Method(methodHandle, default(RuntimeTypeHandle)); // throws
// after
builder.Method(methodHandle, typeof(Action<string>).TypeHandle);
Defensive patterns

Strategy: validation

Validate before calling

var type = Type.GetTypeFromHandle(delegateType);
if (type is null)
    throw new ArgumentException("Invalid type handle", nameof(delegateType));
builder.Method(handle, delegateType);

Type guard

static bool IsValidTypeHandle(RuntimeTypeHandle h) =>
    Type.GetTypeFromHandle(h) is not null;

Try / catch

try { builder.Method(handle, delegateType); }
catch (ArgumentException ex) when (ex.Message.Contains("GetTypeFromHandle"))
{ /* obtain delegateType from typeof(T).TypeHandle; ensure assembly loaded */ }

Prevention

When it happens

Trigger: Constructing MethodAsDelegateElement with a default/uninitialized RuntimeTypeHandle, a handle to a type in an assembly that was unloaded, or a handle captured incorrectly. CompiledBindingPathBuilder.Method(handle, delegateType) forwards delegateType here.

Common situations: Passing default(RuntimeTypeHandle) instead of typeof(MyDelegate).TypeHandle. Type lives in an assembly not yet loaded or trimmed away (AOT/trimming). Reflection-based capture of a type handle before the assembly is resolved.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/f6b868bcc41235ef. Report an issue: GitHub.