dotnet/maui · error · ArgumentNullException

returnType

Error message

returnType

What it means

Argument null guard in the private BindableProperty constructor: returnType must not be null. Reached through every BindableProperty.Create* factory whenever the value type argument is null. The property records what CLR type its values must have, so a null type makes the property unusable.

Source

Thrown at src/Controls/src/Core/BindableProperty.cs:195

			{ typeof(ulong), new[] { typeof(string), typeof(float), typeof(double), typeof(decimal) } },
			{ typeof(double), new[] { typeof(string) } },
			{ typeof(bool), new[] { typeof(string) } },
		};

		/// <summary>A sentinel object used to indicate that a BindableProperty value has not been set.</summary>
		public static readonly object UnsetValue = new object();

		private static int _nextInternalId = int.MinValue;
		internal readonly int InternalId;

		BindableProperty(string propertyName, [DynamicallyAccessedMembers(ReturnTypeMembers)] Type returnType, [DynamicallyAccessedMembers(DeclaringTypeMembers)] Type declaringType, object defaultValue, BindingMode defaultBindingMode = BindingMode.OneWay,
								 ValidateValueDelegate validateValue = null, BindingPropertyChangedDelegate propertyChanged = null, BindingPropertyChangingDelegate propertyChanging = null,
								 CoerceValueDelegate coerceValue = null, BindablePropertyBindingChanging bindingChanging = null, bool isReadOnly = false, CreateDefaultValueDelegate defaultValueCreator = null)
		{
			if (propertyName == null)
				throw new ArgumentNullException(nameof(propertyName));
			if (returnType is null)
				throw new ArgumentNullException(nameof(returnType));
			if (declaringType is null)
				throw new ArgumentNullException(nameof(declaringType));
			
			InternalId = Interlocked.Increment(ref _nextInternalId);

			// don't use Enum.IsDefined as its redonkulously expensive for what it does
			if (defaultBindingMode != BindingMode.Default && defaultBindingMode != BindingMode.OneWay && defaultBindingMode != BindingMode.OneWayToSource && defaultBindingMode != BindingMode.TwoWay && defaultBindingMode != BindingMode.OneTime)
				throw new ArgumentException($"Not a valid type of BindingMode. Property: {returnType} {declaringType.Name}.{propertyName}. Default binding mode: {defaultBindingMode}", nameof(defaultBindingMode));

			if (defaultValue == null && Nullable.GetUnderlyingType(returnType) == null && returnType.IsValueType)
				defaultValue = Activator.CreateInstance(returnType);

			if (defaultValue != null && !returnType.IsInstanceOfType(defaultValue))
				throw new ArgumentException($"Default value did not match return type. Property: {returnType} {declaringType.Name}.{propertyName} Default value type: {defaultValue.GetType().Name}, ", nameof(defaultValue));

			if (defaultBindingMode == BindingMode.Default)
				defaultBindingMode = BindingMode.OneWay;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Pass the concrete value type as the second argument, e.g. typeof(string).
  2. For generic hosts, resolve the open type explicitly (typeof(T)) and confirm T is constrained.
  3. Guard computed Type values for null before calling Create.

Example fix

// before
public static readonly BindableProperty ValueProperty =
    BindableProperty.Create(nameof(Value), _resolvedType, typeof(MyView));

// after
public static readonly BindableProperty ValueProperty =
    BindableProperty.Create(nameof(Value), typeof(string), typeof(MyView));
Defensive patterns

Strategy: validation

Validate before calling

if (valueType is null) throw new ArgumentNullException(nameof(valueType));
var bp = BindableProperty.Create(nameof(X), valueType, typeof(MyView));

Type guard

static bool IsKnownValueType(Type t) => t is not null && t.IsSerializable;

Prevention

When it happens

Trigger: BindableProperty.Create(nameof(X), null, typeof(MyView)); passing a Type variable that resolved to null (e.g. from a generic whose type argument was erased); generated code that emits typeof() against an unresolved symbol.

Common situations: Building a generic control and forgetting to substitute the type argument; refactoring that leaves typeof(RemovedClass); source generators emitting null type tokens.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/750b69d86324c548. Report an issue: GitHub.