dotnet/aspnetcore · error · InvalidOperationException
Multiple properties were found on component type
Error message
Multiple properties were found on component type '{targetType.FullName}' with 'ParameterAttribute.CaptureUnmatchedValues'. Only a single property per type can use 'ParameterAttribute.CaptureUnmatchedValues'. Properties: What it means
ThrowForMultipleCaptureUnmatchedValuesParameters scans a component type during cache construction and throws if more than one property is annotated with [Parameter(CaptureUnmatchedValues = true)]. Blazor allows exactly one unmatched-attributes sink per component; ambiguity about which property receives splatted attributes is a design error. The message lists the offending property names sorted ordinally.
Solutions
- Keep only one property with [Parameter(CaptureUnmatchedValues = true)] per component type; remove the attribute from the others.
- If inheritance introduced a second sink, remove it from the derived type or break the inheritance.
- Merge unmatched attributes into a single Dictionary<string, object> property.
Example fix
// before
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? Attributes { get; set; }
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? Extra { get; set; } // throws
// after
[Parameter(CaptureUnmatchedValues = true)]
public Dictionary<string, object>? Attributes { get; set; } Defensive patterns
Strategy: type-guard
Type guard
static bool HasSingleCaptureSink(Type componentType)
{
int count = componentType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Count(p => p.GetCustomAttribute<ParameterAttribute>()?.CaptureUnmatchedValues == true);
return count <= 1;
}
Assert.True(HasSingleCaptureSink(typeof(MyComponent))); Prevention
- Keep exactly one CaptureUnmatchedValues property per component (including inherited ones).
- Add a unit test asserting the single-sink invariant per component type.
- When inheriting, verify the base type does not already declare a sink.
When it happens
Trigger: Declaring two (or more) properties each with [Parameter(CaptureUnmatchedValues = true)] on the same component type. Copy-pasting a capture-sink property and forgetting to remove the original. Inheritance where both base and derived declare a capture sink.
Common situations: Component library authors adding a second splat sink by mistake. Refactoring that duplicates the Attributes property. Inherited components where the derived type adds its own sink alongside an inherited one.
Related errors
- The property ' ' on component type ' ' cannot be used with…
- 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 set…
- The type ' ' declares a parameter matching the name ' '…
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/097fdc0bb4ee72da.
Report an issue: GitHub.
Appendix: 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 3600ca084e)