dotnet/aspnetcore · error · InvalidOperationException

The type ' ' declares a parameter matching the name ' '…

Error message

The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public.

What it means

WritersForType constructor in ComponentProperties requires every [Parameter]-annotated property to have a public setter so the framework can assign incoming values. If propertyInfo.SetMethod is null (no setter) or not public, the PropertySetter cannot be built and the type cache throws during first use of the component. This is the component-parameter analogue of the persistent-service setter check.

Solutions

  1. Make the setter public: [Parameter] public int Count { get; set; }.
  2. For init patterns use 'public init'.
  3. If encapsulation is required, perform validation in OnParametersSet or in a public setter body rather than hiding the setter.

Example fix

// before
[Parameter]
public int Count { get; private set; }

// after
[Parameter]
public int Count { get; set; }
Defensive patterns

Strategy: type-guard

Type guard

static bool HasPublicParameterSetter(PropertyInfo p)
    => p.GetCustomAttribute<ParameterAttribute>() != null
       && p.SetMethod != null && p.SetMethod.IsPublic;

foreach (var p in typeof(MyComponent).GetProperties())
{
    if (p.GetCustomAttribute<ParameterAttribute>() != null)
        Assert.True(HasPublicParameterSetter(p));
}

Prevention

When it happens

Trigger: Declaring [Parameter] on a property with a private/protected/internal setter, an init-only setter that is non-public, or no setter at all. The error surfaces when the component is first rendered or its writers cache is built.

Common situations: Encapsulating a parameter's value with a private setter to enforce validation, while still annotating it [Parameter]. Using { get; } without a setter. Migrating a property to a parameter without exposing the setter.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/cc296bec53620fee. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/Components/src/Reflection/ComponentProperties.cs:321

                        default:
                            break;
                    }
                }

                // A property cannot accept direct parameters if it's annotated with a cascading value attribute, unless it's a
                // SupplyParameterFromQueryAttribute. This is to retain backwards compatibility with previous versions of the
                // SupplyParameterFromQuery feature that did not utilize cascading values, and thus did not have this limitation.
                var acceptsDirectParameters = parameterAttribute is not null && cascadingParameterAttribute is null or SupplyParameterFromQueryAttribute;
                var acceptsCascadingParameters = cascadingParameterAttribute is not null;
                if (!acceptsDirectParameters && !acceptsCascadingParameters)
                {
                    continue;
                }

                var propertyName = propertyInfo.Name;
                if (parameterAttribute != null && (propertyInfo.SetMethod == null || !propertyInfo.SetMethod.IsPublic))
                {
                    throw new InvalidOperationException(
                        $"The type '{targetType.FullName}' declares a parameter matching the name '{propertyName}' that is not public. Parameters must be public.");
                }

                var propertySetter = new PropertySetter(targetType, propertyInfo)
                {
                    AcceptsDirectParameters = acceptsDirectParameters,
                    AcceptsCascadingParameters = acceptsCascadingParameters,
                };

                if (_underlyingWriters.ContainsKey(propertyName))
                {
                    throw new InvalidOperationException(
                        $"The type '{targetType.FullName}' declares more than one parameter matching the " +
                        $"name '{propertyName.ToLowerInvariant()}'. Parameter names are case-insensitive and must be unique.");
                }

                _underlyingWriters.Add(propertyName, propertySetter);

View on GitHub (pinned to 3600ca084e)