dotnet/aspnetcore · error · InvalidOperationException

The type '{targetType.FullName}' declares a parameter matchi

Error message

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

What it means

Thrown by ComponentProperties.WritersForType constructor when a [Parameter]-decorated property has a setter that is null or non-public. Component parameters require a public setter so the framework can write incoming values via PropertySetter.

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 294cab2f9b)

Solutions

  1. Make the setter public: { get; set; }.
  2. If immutability is required, note that Blazor parameters must be publicly settable - restructure rather than hiding the setter.
  3. For records, declare parameter properties with explicit public setters.
  4. Audit [Parameter] properties for non-public setters before runtime.

Example fix

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

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

Strategy: validation

Validate before calling

// Audit component types: every [Parameter] property must have a public setter.
static void ValidateComponentParameters(params Type[] componentTypes)
{
    foreach (var t in componentTypes)
    foreach (var p in t.GetProperties(
        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
    {
        if (p.GetCustomAttribute<ParameterAttribute>() is null) continue;
        if (p.GetSetMethod(nonPublic: false) is null)
            throw new InvalidOperationException(
                $"{t.FullName}.{p.Name} has [Parameter] but no public setter.");
    }
}

Type guard

static bool HasPublicSetter(PropertyInfo p) => p.GetSetMethod(nonPublic: false) is not null;

Prevention

When it happens

Trigger: Declaring [Parameter] on a get-only property, an init-only property, or a property with a private/protected/internal setter.

Common situations: Using { get; init; }, { get; }, or { get; private set; } for a parameter; record positional parameters that produce non-public setters; refactoring that changed setter visibility.

Related errors


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