dotnet/maui · error · InvalidOperationException
The BindableProperty "{property.PropertyName}" is readonly.
Error message
The BindableProperty "{property.PropertyName}" is readonly. What it means
InvalidOperationException thrown by CoerceValue(BindableProperty, checkAccess:true) when the property is read-only. The public CoerceValue(BindableProperty) passes checkAccess:true, so attempting to coerce a read-only BindableProperty through that overload is rejected; read-only properties must be coerced via their BindablePropertyKey. The message names the offending property.
Source
Thrown at src/Controls/src/Core/BindableObject.cs:855
/// <exception cref="ArgumentNullException">Thrown when <paramref name="propertyKey"/> is <see langword="null"/>.</exception>
/// <exception cref="InvalidOperationException">Thrown when the bindable property identified by <paramref name="propertyKey"/> is read-only.</exception>
/// <exception cref="ArgumentException">Thrown when the value is invalid according to the assigned logic in <see cref="BindableProperty.ValidateValueDelegate"/>.</exception>
/// <remarks>If <see cref="BindableProperty.CoerceValueDelegate"/> is not assigned to, nothing will happen.</remarks>
public void CoerceValue(BindablePropertyKey propertyKey)
{
if (propertyKey == null)
throw new ArgumentNullException(nameof(propertyKey));
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 AWAYView on GitHub (pinned to f377ff1c5e)
Solutions
- Use the CoerceValue(BindablePropertyKey) overload for read-only properties, passing the key returned from CreateReadOnly.
- Expose the key (e.g. as a protected/internal property) so external coercers can call the key-based overload.
- If you control the property, decide whether it truly needs to be read-only.
Example fix
// before obj.CoerceValue(MyControl.ReadOnlyProp); // IsReadOnly=true -> throws // after obj.CoerceValue(MyControl.ReadOnlyPropKey); // key-based overload, checkAccess=false
Defensive patterns
Strategy: type-guard
Validate before calling
if (property.IsReadOnly)
throw new InvalidOperationException("Use the BindablePropertyKey overload for read-only properties.");
obj.CoerceValue(property); Type guard
static bool IsCoerciblePublicly(Microsoft.Maui.Controls.BindableProperty p) => p is not null && !p.IsReadOnly;
Try / catch
try { obj.CoerceValue(prop); }
catch (InvalidOperationException) { obj.CoerceValue(propKey); } Prevention
- Track whether a property is read-only and keep its key accessible for coercion.
- Expose keys to code that needs to coerce read-only properties.
When it happens
Trigger: Calling the public CoerceValue(someReadOnlyBindableProperty) on a property declared with BindableProperty.CreateReadOnly (its BindableProperty has IsReadOnly=true).
Common situations: Coercing a read-only property from code that only holds the BindableProperty (not the key); generic coercion utilities that do not distinguish read-only properties.
Related errors
- Value is an invalid value for {property.PropertyName}
- Implement INativeElementView on cell renderer: {ContentCell.
- No UIViewController found to present.
- You MUST invoke LoadApplication () before calling base.Finis
- call Forms.Init() before this
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/33ad55fe109964c1.
Report an issue: GitHub.