dotnet/aspnetcore · error · InvalidOperationException

The type '{targetType.FullName}' declares more than one para

Error message

The type '{targetType.FullName}' declares more than one parameter matching the name '{propertyName.ToLowerInvariant()}'. Parameter names are case-insensitive and must be unique.

What it means

Blazor component parameter names are matched case-insensitively. When the framework builds the parameter cache for a component type, it detects that two properties decorated with [Parameter] or [CascadingParameter] resolve to the same lowercased name and throws InvalidOperationException. This is a design-time correctness check that prevents ambiguous parameter binding at runtime.

Source

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

                    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);

                if (parameterAttribute != null && parameterAttribute.CaptureUnmatchedValues)
                {
                    // This is an "Extra" parameter.
                    //
                    // There should only be one of these.
                    if (CaptureUnmatchedValuesWriter != null)
                    {
                        ThrowForMultipleCaptureUnmatchedValuesParameters(targetType);
                    }

                    // It must be able to hold a Dictionary<string, object> since that's what we create.
                    if (!propertyInfo.PropertyType.IsAssignableFrom(typeof(Dictionary<string, object>)))

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Inspect the component type named in the error and search for [Parameter] or [CascadingParameter] properties that differ only by case.
  2. Check all base classes of the component type for parameters whose names collide case-insensitively with the derived class's parameters.
  3. Rename one of the colliding properties to a distinct name and update all usages in markup (.razor files) and C# code.
  4. If using [CascadingParameter] alongside [Parameter] for the same property, combine them on a single property declaration.

Example fix

// before
[Parameter] public string? Title { get; set; }
[Parameter] public string? title { get; set; } // collides

// after
[Parameter] public string? Title { get; set; }
[Parameter] public string? Subtitle { get; set; }
Defensive patterns

Strategy: validation

Validate before calling

// Validate before component registration
static void ValidateNoDuplicateParameterNames(Type componentType)
{
    var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
    foreach (var prop in componentType.GetProperties(
        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
    {
        var hasParam = prop.GetCustomAttribute<ParameterAttribute>() != null
            || prop.GetCustomAttribute<CascadingParameterAttribute>() != null;
        if (!hasParam) continue;
        if (!seen.Add(prop.Name))
            throw new InvalidOperationException(
                $"Duplicate parameter '{prop.Name}' on {componentType.FullName}");
    }
}
// Call: ValidateNoDuplicateParameterNames(typeof(MyComponent));

Type guard

// Compile-time guard via generic constraint is not possible for attribute-based params.
// Use a Roslyn analyzer or source generator to detect duplicate [Parameter] names at build time.

Prevention

When it happens

Trigger: A component declares two parameter properties whose names differ only by case (e.g., [Parameter] public string? Title and [Parameter] public string? title). Also triggered when a derived component redeclares a [Parameter] that already exists on a base component with different casing, or when an explicitly implemented interface property collides with a declared parameter name.

Common situations: Copy-pasting a property and renaming with different casing; inheriting from a base component that already declares a similarly-named parameter; refactoring a property name and accidentally leaving the old casing behind; VB.NET interop where case-insensitivity is the norm but clashes with Blazor's own case-insensitive matching.

Related errors


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