{"record":{"id":"07685eb07761672d","repo":"dotnet/aspnetcore","slug":"multiple-properties-were-found-on-component-type","errorCode":null,"errorMessage":"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:","messagePattern":"Multiple properties were found on component type '(.+?)' with '(.+?)\\.(.+?)'\\. Only a single property per type can use '(.+?)\\.(.+?)'\\. Properties:","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Reflection/ComponentProperties.cs","lineNumber":260,"sourceCode":"            $\"when also used to capture unmatched values. Unmatched values:\" + Environment.NewLine +\n            string.Join(Environment.NewLine, unmatched.Keys));\n    }\n\n    [DoesNotReturn]\n    private static void ThrowForMultipleCaptureUnmatchedValuesParameters([DynamicallyAccessedMembers(Component)] Type targetType)\n    {\n        var propertyNames = new List<string>();\n        foreach (var property in targetType.GetProperties(BindablePropertyFlags))\n        {\n            if (property.GetCustomAttribute<ParameterAttribute>()?.CaptureUnmatchedValues == true)\n            {\n                propertyNames.Add(property.Name);\n            }\n        }\n\n        propertyNames.Sort(StringComparer.Ordinal);\n\n        throw new InvalidOperationException(\n            $\"Multiple properties were found on component type '{targetType.FullName}' with \" +\n            $\"'{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Only a single property \" +\n            $\"per type can use '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}'. Properties:\" + Environment.NewLine +\n            string.Join(Environment.NewLine, propertyNames));\n    }\n\n    [DoesNotReturn]\n    private static void ThrowForInvalidCaptureUnmatchedValuesParameterType(Type targetType, PropertyInfo propertyInfo)\n    {\n        throw new InvalidOperationException(\n            $\"The property '{propertyInfo.Name}' on component type '{targetType.FullName}' cannot be used \" +\n            $\"with '{nameof(ParameterAttribute)}.{nameof(ParameterAttribute.CaptureUnmatchedValues)}' because it has the wrong type. \" +\n            $\"The property must be assignable from 'Dictionary<string, object>'.\");\n    }\n\n    private sealed class WritersForType\n    {\n        private const int MaxCachedWriterLookups = 100;","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/Reflection/ComponentProperties.cs#L242-L278","documentation":"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.","triggerScenarios":"Two properties on the same component both declared [Parameter(CaptureUnmatchedValues = true)]; a base component declares one and a derived component declares another.","commonSituations":"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.","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."],"exampleFix":"// before\n[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> A { get; set; }\n[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> B { get; set; }\n\n// after\n[Parameter(CaptureUnmatchedValues = true)] public Dictionary<string, object> A { get; set; }","handlingStrategy":"validation","validationCode":"// Ensure at most one CaptureUnmatchedValues parameter per type (including base types).\nstatic int CountCaptureUnmatchedValues(Type t)\n{\n    int n = 0;\n    for (var type = t; type is not null; type = type.BaseType)\n    foreach (var p in type.GetProperties(\n        BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))\n    {\n        if (p.GetCustomAttribute<ParameterAttribute>()?.CaptureUnmatchedValues == true) n++;\n    }\n    return n;\n}","typeGuard":"static bool HasSingleCaptureUnmatchedValues(Type t) => CountCaptureUnmatchedValues(t) <= 1;","tryCatchPattern":null,"preventionTips":["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."],"tags":["blazor","parameters","capture-unmatched","attributes","rendering"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}