dotnet/aspnetcore · error · InvalidOperationException
Multiple properties were found on component type '{targetTyp
Error message
Multiple properties were found on component type '{targetType.FullName}' with '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Only a single property per type can use '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Properties: What it means
Thrown by ComponentProperties.ThrowForMultipleCaptureUnmatchedValuesParameters when more than one property on a component is decorated with [Parameter(CaptureUnmatchedValues = true)]. Only a single catch-all parameter is permitted per type, including across the inheritance chain.
Source
Thrown at src/Components/Components/src/Reflection/ComponentProperties.cs:260
$"when also used to capture unmatched values. Unmatched values:" + Environment.NewLine +
string.Join(Environment.NewLine, unmatched.Keys));
}
[DoesNotReturn]
private static void ThrowForMultipleCaptureUnmatchedValuesParameters([DynamicallyAccessedMembers(Component)] Type targetType)
{
var propertyNames = new List<string>();
foreach (var property in targetType.GetProperties(BindablePropertyFlags))
{
if (property.GetCustomAttribute<ParameterAttribute>()?.CaptureUnmatchedValues == true)
{
propertyNames.Add(property.Name);
}
}
propertyNames.Sort(StringComparer.Ordinal);
throw new InvalidOperationException(
$"Multiple properties were found on component type '{targetType.FullName}' with " +
$"'{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Only a single property " +
$"per type can use '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Properties:" + Environment.NewLine +
string.Join(Environment.NewLine, propertyNames));
}
[DoesNotReturn]
private static void ThrowForInvalidCaptureUnmatchedValuesParameterType(Type targetType, PropertyInfo propertyInfo)
{
throw new InvalidOperationException(
$"The property '{propertyInfo.Name}' on component type '{targetType.FullName}' cannot be used " +
$"with '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}' because it has the wrong type. " +
$"The property must be assignable from 'Dictionary<string, object>'.");
}
private sealed class WritersForType
{
private const int MaxCachedWriterLookups = 100;View on GitHub (pinned to 294cab2f9b)
Solutions
- Keep exactly one CaptureUnmatchedValues property per component, including inherited ones.
- If a base type already declares it, do not redeclare it in the derived type.
- Consolidate the two catch-all properties into a single Dictionary<string, object> parameter.
Example fix
// before
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> A { get; set; }
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> B { get; set; }
// after
[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> A { get; set; } Defensive patterns
Strategy: validation
Validate before calling
// Ensure at most one CaptureUnmatchedValues parameter per type (including base types).
static int CountCaptureUnmatchedValues(Type t)
{
int n = 0;
for (var type = t; type is not null; type = type.BaseType)
foreach (var p in type.GetProperties(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
if (p.GetCustomAttribute<ParameterAttribute>()?.CaptureUnmatchedValues == true) n++;
}
return n;
} Type guard
static bool HasSingleCaptureUnmatchedValues(Type t) => CountCaptureUnmatchedValues(t) <= 1;
Prevention
- Declare exactly one [Parameter(CaptureUnmatchedValues = true)] per component, including inherited ones.
- Do not redeclare a catch-all in a derived type if the base already has one.
- When merging components, consolidate their catch-all parameters into one.
- Run a build-time audit over your component hierarchy.
When it happens
Trigger: Two properties on the same component both declared [Parameter(CaptureUnmatchedValues = true)]; a base component declares one and a derived component declares another.
Common situations: Copy-paste of a catch-all parameter; inheriting a base with a catch-all and adding another in the derived type; merging two components that each had their own catch-all.
Related errors
- The property '{parameterName}' on component type '{targetTyp
- Object of type '{targetType.FullName}' has a property matchi
- The property '{propertyInfo.Name}' on component type '{targe
- The type '{targetType.FullName}' declares a parameter matchi
- Unable to set property '{parameterName}' on object of type '
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/07685eb07761672d.
Report an issue: GitHub.