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

  1. Ensure the [PersistentState] cascading parameter has a public getter.
  2. Verify the property name on the component matches what the attribute/parameter info expects.
  3. Avoid hiding the getter in derived component types.
  4. 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

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


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/03f4bf0ebac1d056. Report an issue: GitHub.