{"record":{"id":"339e4793e78173bd","repo":"dotnet/aspnetcore","slug":"unknown-type-type-for-parameter-parametern","errorCode":null,"errorMessage":"Unknown type '${type}' for parameter '${parameterName}'","messagePattern":"Unknown type '(.+?)' for parameter '(.+?)'","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Components/CustomElements/src/js/BlazorCustomElements.ts","lineNumber":136,"sourceCode":"            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}\n\n// JSON-primitive types, plus for those whose .NET equivalent isn't nullable, a '?' to indicate nullability","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/CustomElements/src/js/BlazorCustomElements.ts#L118-L154","documentation":"Thrown by parseAttributeValue's default branch when the parameter's declared JSComponentParameterType is none of 'string','boolean','boolean?','number','number?','object'. This is a registration-time contract violation: the type metadata supplied to RegisterAsCustomElement contains an unrecognized type identifier.","triggerScenarios":"Registering a custom element whose parameter descriptors include an unsupported type string (e.g. 'date', 'array', 'int', 'guid', a custom enum). The attribute parser has no branch for it and falls through to default.","commonSituations":"Hand-crafting JSComponentParameter[] metadata incorrectly, a version mismatch where newer parameter types are forwarded to an older JS runtime that doesn't know them, or a serializer that emitted the C# type name instead of the expected JSON-primitive alias.","solutions":["Map every non-primitive parameter to 'object' and set it via the JS property (object is the catch-all for complex types).","Map Date/Time/DateTimeOffset parameters to 'string' (ISO 8601) and parse on the .NET side, or use a string [Parameter].","Ensure you are using a matching pair of .NET runtime and JS custom-elements bundle so the type vocabulary agrees.","Inspect the JSComponentParameter[] passed to RegisterAsCustomElement and confirm every entry's 'type' is one of the six supported literals."],"exampleFix":"// before: descriptor with unsupported type\nRegisterAsCustomElement('my-comp', [\n  { name: 'Created', type: 'date' } // unsupported\n]);\n\n// after: use 'string' for dates\nRegisterAsCustomElement('my-comp', [\n  { name: 'Created', type: 'string' }\n]);","handlingStrategy":"validation","validationCode":"const SUPPORTED = new Set(['string', 'boolean', 'boolean?', 'number', 'number?', 'object']);\nfunction validateDescriptors(params: { name: string; type: string }[]) {\n  for (const p of params) {\n    if (!SUPPORTED.has(p.type)) {\n      throw new Error(`Unsupported parameter type '${p.type}' for '${p.name}'. Use one of: ${[...SUPPORTED].join(', ')}`);\n    }\n  }\n}\nvalidateDescriptors(parameterDescriptors);","typeGuard":"type SupportedType = 'string' | 'boolean' | 'boolean?' | 'number' | 'number?' | 'object';\nfunction isSupportedType(t: string): t is SupportedType {\n  return ['string', 'boolean', 'boolean?', 'number', 'number?', 'object'].includes(t);\n}","tryCatchPattern":"// Thrown synchronously inside attributeChangedCallback; catch at the dispatcher.\ntry {\n  el.setAttribute(p.name, raw);\n} catch (e) {\n  if (/Unknown type/.test((e as Error).message)) {\n    console.error('Descriptor type mismatch — regenerate JSComponentParameter metadata');\n  } else throw e;\n}","preventionTips":["Generate JSComponentParameter[] from .NET metadata rather than hand-authoring.","Keep the .NET runtime and JS bundle versions aligned so the type vocabulary matches.","Map every non-primitive .NET type to 'object' in descriptors.","Add a registration-time assertion over the descriptor type set."],"tags":["blazor-custom-elements","registration","type-coercion","version-mismatch"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}