dotnet/aspnetcore · error · InvalidOperationException
The type ' ' declares more than one parameter matching the…
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
WritersForType builds its parameter-name cache case-insensitively (StringComparer.OrdinalIgnoreCase). When two properties both resolve to the same parameter name (e.g., 'Count' and 'count'), the second registration collides and throws. Blazor parameter names are case-insensitive on the consumer side, so duplicate names differing only by case are ambiguous and rejected at cache-construction time.
Solutions
- Rename one of the colliding parameters so the names are unique case-insensitively.
- If the collision comes from inheritance, remove the duplicate in the derived type or rename the base.
- Establish a casing convention (PascalCase for parameters) across the component hierarchy.
Example fix
// before
[Parameter] public string? Title { get; set; }
[Parameter] public string? title { get; set; } // throws
// after
[Parameter] public string? Title { get; set; }
[Parameter] public string? Subtitle { get; set; } Defensive patterns
Strategy: validation
Validate before calling
// Detect case-insensitive parameter name collisions across the type hierarchy.
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var p in typeof(MyComponent).GetProperties(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
bool isParam = p.GetCustomAttribute<ParameterAttribute>() != null
|| p.GetCustomAttributes().OfType<CascadingParameterAttributeBase>().Any();
if (!isParam) continue;
if (!seen.Add(p.Name))
throw new InvalidOperationException($"Duplicate parameter name '{p.Name}' (case-insensitive).");
} Prevention
- Use distinct, PascalCase parameter names throughout the hierarchy.
- Add a unit test that detects case-insensitive duplicates per component type.
- When inheriting, check the base type's parameters before adding new ones.
When it happens
Trigger: Declaring two [Parameter] (or [CascadingParameter]) properties on the same component whose names differ only by case, e.g., 'Title' and 'title'. The collision is detected when _underlyingWriters already contains the lower-cased key. Inheritance can also cause it if base and derived declare same-named parameters.
Common situations: Refactoring that introduces a similarly-named parameter. Inherited components overriding or shadowing a base parameter with a differently-cased duplicate. Copy-paste errors. Casing inconsistencies between C# property name and a Razor attribute.
Related errors
- Multiple properties were found on component type
- Object of type ' ' does not have a property matching the…
- Object of type ' ' has a property matching the name ' '…
- The property ' ' on component type ' ' cannot be used with…
- The type ' ' declares a parameter matching the name ' '…
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/dae09a1338998cbc.
Report an issue: GitHub.
Appendix: 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 3600ca084e)