{"record":{"id":"89865827252d7b8b","repo":"dotnet/aspnetcore","slug":"the-property-propertyinfo-name-on-component-ty","errorCode":null,"errorMessage":"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>'.","messagePattern":"The property '(.+?)' on component type '(.+?)' cannot be used with '(.+?)\\.(.+?)' because it has the wrong type\\. The property must be assignable from 'Dictionary<string, object>'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Components/Components/src/Reflection/ComponentProperties.cs","lineNumber":270,"sourceCode":"            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;\n        private readonly Dictionary<string, PropertySetter> _underlyingWriters;\n        private readonly ConcurrentDictionary<string, PropertySetter?> _referenceEqualityWritersCache;\n\n        public WritersForType([DynamicallyAccessedMembers(Component)] Type targetType)\n        {\n            _underlyingWriters = new Dictionary<string, PropertySetter>(StringComparer.OrdinalIgnoreCase);\n            _referenceEqualityWritersCache = new ConcurrentDictionary<string, PropertySetter?>(ReferenceEqualityComparer.Instance);\n\n            foreach (var propertyInfo in GetCandidateBindableProperties(targetType))\n            {","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Components/src/Reflection/ComponentProperties.cs#L252-L288","documentation":"Thrown by ComponentProperties.ThrowForInvalidCaptureUnmatchedValuesParameterType when the CaptureUnmatchedValues property's type is not assignable from Dictionary<string, object>. The framework instantiates a Dictionary<string, object> to hold unmatched values, so the property type must accept that exact type.","triggerScenarios":"[Parameter(CaptureUnmatchedValues = true)] on a property whose type cannot hold a Dictionary<string, object>, e.g. Dictionary<string, string>, List<KeyValuePair<string, object>>, or object-typed collections that are not assignable.","commonSituations":"Using Dictionary<string, string> to capture attributes; a custom collection type; assuming any IDictionary would work when the type parameter differs.","solutions":["Change the property type to Dictionary<string, object> (the canonical type).","IDictionary<string, object> also works since Dictionary<string, object> is assignable to it; use that if you only need the interface.","Avoid Dictionary<string, string> or other generic variants - attribute values are object."],"exampleFix":"// before\n[Parameter(CaptureUnmatchedValues = true)]\npublic Dictionary<string, string> Extra { get; set; }\n\n// after\n[Parameter(CaptureUnmatchedValues = true)]\npublic Dictionary<string, object> Extra { get; set; }","handlingStrategy":"type-guard","validationCode":"// Validate that a CaptureUnmatchedValues property can hold Dictionary<string, object>.\nstatic bool IsValidCaptureType(Type propertyType)\n    => propertyType.IsAssignableFrom(typeof(Dictionary<string, object>));","typeGuard":"static bool CanHoldAttributeDictionary(Type propertyType)\n    => propertyType.IsAssignableFrom(typeof(Dictionary<string, object>));","tryCatchPattern":null,"preventionTips":["Type catch-all parameters as Dictionary<string, object> (or IDictionary<string, object>).","Never use Dictionary<string, string> or unrelated collection types for unmatched attributes.","Add a build-time check that the property type is assignable from Dictionary<string, object>.","Remember attribute values are object, not string."],"tags":["blazor","parameters","capture-unmatched","type-mismatch","rendering"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}