{"record":{"id":"75f99fc2175160e6","repo":"dotnet/aspnetcore","slug":"the-parameter-parametername-accepts-a-complex","errorCode":null,"errorMessage":"The parameter '${parameterName}' accepts a complex-typed object so it cannot be set using an attribute. Try setting it as a element property instead.","messagePattern":"The parameter '(.+?)' accepts a complex-typed object so it cannot be set using an attribute\\. Try setting it as a element property instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/CustomElements/src/js/BlazorCustomElements.ts","lineNumber":134,"sourceCode":"          case 'false':\n          case 'False':\n            return false;\n          default:\n            throw new Error(`Invalid boolean value '${attributeValue}' for parameter '${parameterName}'`);\n        }\n      case 'number':\n        const number = Number(attributeValue);\n        if (Number.isNaN(number)) {\n          throw new Error(`Invalid number value '${attributeValue}' for parameter '${parameterName}'`);\n        } else {\n          return number;\n        }\n      case 'boolean?':\n        return attributeValue ? BlazorCustomElement.parseAttributeValue(attributeValue, 'boolean', parameterName) : null;\n      case 'number?':\n        return attributeValue ? BlazorCustomElement.parseAttributeValue(attributeValue, 'number', parameterName) : null;\n      case 'object':\n        throw new Error(`The parameter '${parameterName}' accepts a complex-typed object so it cannot be set using an attribute. Try setting it as a element property instead.`);\n      default:\n        throw new Error(`Unknown type '${type}' for parameter '${parameterName}'`);\n    }\n  }\n}\n\nfunction dasherize(value: string): string {\n  return camelCase(value).replace(/([A-Z])/g, \"-$1\").toLowerCase();\n}\n\nfunction camelCase(value: string): string {\n  return value[0].toLowerCase() + value.substring(1);\n}\n\ninterface JSComponentParameter {\n  name: string;\n  type: JSComponentParameterType;\n}","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/src/Components/CustomElements/src/js/BlazorCustomElements.ts#L116-L152","documentation":"Thrown by parseAttributeValue for a parameter registered with type 'object'. Complex-typed parameters cannot be expressed as HTML attribute strings (which are always text), so the framework refuses the assignment and directs you to the property setter, which is the only path that can pass a structured value to .NET.","triggerScenarios":"Attempting to set an object/array/complex-typed [Parameter] through an HTML attribute (markup or setAttribute) on a Blazor custom element. The observedAttributes machinery routes the string into parseAttributeValue, which hits the 'object' case.","commonSituations":"Trying <my-grid options=\"{pageSize:10}\"> instead of using the JS property; porting Razor component APIs that take POCO/record parameters to custom-element form; forgetting that only primitive parameters can be attribute-bound.","solutions":["Assign the value via the camelCase JS property the framework defines on the element, not via setAttribute.","Confirm the [Parameter] type actually requires an object; if it is logically primitive, change the JS-side registration type to 'string'/'number'/'boolean'.","Build the object in JS and assign after the element is connected so Blazor picks it up via _supplyUpdatedParameters."],"exampleFix":"// before\nel.setAttribute('chartOptions', '{\"legend\":true}'); // throws\n\n// after — assign as a property, the framework-defined setter handles it\nel.chartOptions = { legend: true };","handlingStrategy":"type-guard","validationCode":"// Route object-typed parameters to the property setter, never the attribute.\nfunction setParam(el, name, value) {\n  if (value !== null && typeof value === 'object') {\n    el[camelCase(name)] = value; // framework-defined setter\n  } else {\n    el.setAttribute(dasherize(name), value);\n  }\n}","typeGuard":"function shouldUseProperty(value) {\n  return value !== null && typeof value === 'object';\n}","tryCatchPattern":"try {\n  el.setAttribute(name, value);\n} catch (e) {\n  if (/cannot be set using an attribute/.test(e.message)) {\n    el[camelCase(name)] = value;\n  } else throw e;\n}","preventionTips":["Use the JS property setter for any object/array parameter.","Document which parameters are object-typed so authors do not attempt attribute binding.","Keep object parameters off the observedAttributes list to avoid accidental setAttribute paths.","Pre-coerce structured values to JSON only if a string parameter is genuinely intended."],"tags":["blazor-custom-elements","attribute-parsing","object","complex-type"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}