dotnet/aspnetcore · error · InvalidOperationException
A public property '{propertyName}' on component type '{type.
Error message
A public property '{propertyName}' on component type '{type.FullName}' with a public getter wasn't found. What it means
Thrown by PersistentValueProviderComponentSubscription.PropertyGetterFactory when resolving the getter for a [PersistentState] cascading parameter on a component and the property info is null or its GetMethod is null/non-public. The subscription needs to read the current property value to persist it across render cycles.
Source
Thrown at src/Components/Components/src/PersistentState/PersistentValueProviderComponentSubscription.cs:234
var serializerType = typeof(PersistentComponentStateSerializer<>).MakeGenericType(type);
var serializer = serviceProvider.GetService(serializerType);
// The generic class now inherits from the internal interface, so we can cast directly
return serializer as IPersistentComponentStateSerializer;
}
[UnconditionalSuppressMessage(
"Trimming",
"IL2077:Target parameter argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method. The source field does not have matching annotations.",
Justification = "Properties of rendered components are preserved through other means and won't get trimmed.")]
private static PropertyGetter PropertyGetterFactory((Type type, string propertyName) key)
{
var (type, propertyName) = key;
var propertyInfo = GetPropertyInfo(type, propertyName);
if (propertyInfo == null || propertyInfo.GetMethod == null || !propertyInfo.GetMethod.IsPublic)
{
throw new InvalidOperationException(
$"A public property '{propertyName}' on component type '{type.FullName}' with a public getter wasn't found.");
}
return new PropertyGetter(type, propertyInfo);
static PropertyInfo? GetPropertyInfo([DynamicallyAccessedMembers(LinkerFlags.Component)] Type type, string propertyName)
=> type.GetProperty(propertyName);
}
private static partial class Log
{
[LoggerMessage(1, LogLevel.Debug, "Persisting value for storage key '{StorageKey}' of type '{PropertyType}' from component '{ComponentType}' for property '{PropertyName}'", EventName = "PersistingValueToState")]
public static partial void PersistingValueToState(ILogger logger, string storageKey, string propertyType, string componentType, string propertyName);
[LoggerMessage(2, LogLevel.Debug, "Skipped persisting null value for storage key '{StorageKey}' of type '{PropertyType}' from component '{ComponentType}' for property '{PropertyName}'", EventName = "SkippedPersistingNullValue")]
public static partial void SkippedPersistingNullValue(ILogger logger, string storageKey, string propertyType, string componentType, string propertyName);
[LoggerMessage(3, LogLevel.Debug, "Restoring value for storage key '{StorageKey}' of type '{PropertyType}' for property '{PropertyName}'", EventName = "RestoringValueFromState")]View on GitHub (pinned to 294cab2f9b)
Solutions
- Ensure the [PersistentState] cascading parameter has a public getter.
- Verify the property name on the component matches what the attribute/parameter info expects.
- Avoid hiding the getter in derived component types.
- Audit component [PersistentState] parameters for public getters.
Example fix
// before
[CascadingParameter] [PersistentState]
public User CurrentUser { get; private set; } // non-public getter on a value-provider param
// after
[CascadingParameter] [PersistentState]
public User CurrentUser { get; set; } Defensive patterns
Strategy: validation
Validate before calling
// Audit component types that use [PersistentState] cascading parameters for a public getter.
static void ValidateComponentPersistentStateParams(params Type[] componentTypes)
{
foreach (var t in componentTypes)
foreach (var p in t.GetProperties(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
if (p.GetCustomAttribute<PersistentStateAttribute>() is null) continue;
if (p.GetGetMethod(nonPublic: false) is null)
throw new InvalidOperationException(
$"Component {t.FullName}.{p.Name} [PersistentState] needs a public getter.");
}
} Type guard
static bool ComponentHasPublicGetter(Type componentType, string propertyName)
=> componentType.GetProperty(propertyName)?.GetGetMethod(nonPublic: false) is not null; Prevention
- Give every [PersistentState] cascading parameter a public getter.
- Keep property names stable; avoid renaming persisted parameters without updating attributes.
- Do not hide the getter in derived component types.
- Audit component [PersistentState] parameters during build/startup.
When it happens
Trigger: A component declares a [PersistentState] cascading parameter whose getter is non-public, or the property cannot be resolved by name on the runtime component type.
Common situations: A [PersistentState] cascading parameter declared with a non-public getter; a property renamed while the persisted attribute still references the old name; a custom component subclass that hides the getter.
Related errors
- The type '{targetType.FullName}' declares a property matchin
- Cannot update existing state: previous state has not been cl
- State already initialized.
- State already persisted.
- The registered callback {registration.Callback.Method.Name}
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/03f4bf0ebac1d056.
Report an issue: GitHub.