dotnet/maui · error · ArgumentException

Value is an invalid value for {property.PropertyName}

Error message

Value is an invalid value for {property.PropertyName}

What it means

ArgumentException thrown by CoerceValue when the property's ValidateValue delegate rejects the current value after coercion, with message 'Value is an invalid value for {property.PropertyName}' and paramName 'currentValue'. This means the stored value violates the validation predicate registered on the BindableProperty (e.g. a range constraint). Coercion is meant to keep values valid, so a post-coerce validation failure indicates the coerce logic and validate logic disagree, or the value was set out-of-band.

Source

Thrown at src/Controls/src/Core/BindableObject.cs:864

			CoerceValue(propertyKey.BindableProperty, checkAccess: false);
		}

		void CoerceValue(BindableProperty property, bool checkAccess)
		{
			if (property == null)
				throw new ArgumentNullException(nameof(property));

			if (checkAccess && property.IsReadOnly)
				throw new InvalidOperationException($"The BindableProperty \"{property.PropertyName}\" is readonly.");

			BindablePropertyContext bpcontext = GetContext(property);
			if (bpcontext == null)
				return;

			object currentValue = bpcontext.Values.GetValue();

			if (property.ValidateValue != null && !property.ValidateValue(this, currentValue))
				throw new ArgumentException($"Value is an invalid value for {property.PropertyName}", nameof(currentValue));

			property.CoerceValue?.Invoke(this, currentValue);
		}

		[Flags]
		internal enum BindableContextAttributes
		{
			IsBeingSet = 1 << 1,
			//GO AWAY
			IsDynamicResource = 1 << 2,
			IsSetFromStyle = 1 << 3,
			IsDefaultValueCreated = 1 << 5,
		}

		internal sealed class BindablePropertyContext
		{
			public BindableContextAttributes Attributes;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Ensure the CoerceValue callback always returns a value that satisfies ValidateValue (clamp to the valid range, not just toward it).
  2. Do not bypass validation when setting values; route writes through SetValue so ValidateValue runs.
  3. If using SetValueCore with Converted/private flags, re-validate before coercing.

Example fix

// before
// coerce returns value unchanged even when out of range
static object Coerce(BindableObject b, object v) => v;
// after
static object Coerce(BindableObject b, object v)
{
    var d = (double)v;
    return Math.Clamp(d, Min, Max); // satisfies ValidateValue(range)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate against the same constraint the property uses before coercing
if (property.ValidateValue is not null && !property.ValidateValue(obj, candidate))
    candidate = ClampToValid(candidate);

Try / catch

try { obj.CoerceValue(property); }
catch (ArgumentException ex) when (ex.ParamName == "currentValue")
{ /* coerce/validate disagree; reset to default or log */ }

Prevention

When it happens

Trigger: A BindableProperty with both a CoerceValue (clamping) and a ValidateValue callback where coercion still leaves an invalid value; setting a value directly that bypasses validation (e.g. via SetValueCore) then coercing; coercion callback not actually fixing the value.

Common situations: Sliders/numeric controls with range validation; custom controls where the coerce and validate constraints were edited independently and drifted; values pushed during deserialization that violate runtime invariants.

Related errors


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