dotnet/aspnetcore · error · Error

The parameter ' ' accepts a complex-typed object so it…

Error message

The parameter '${parameterName}' accepts a complex-typed object so it cannot be set using an attribute. Try setting it as a element property instead.

What it means

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.

Solutions

  1. Assign the value via the camelCase JS property the framework defines on the element, not via setAttribute.
  2. Confirm the [Parameter] type actually requires an object; if it is logically primitive, change the JS-side registration type to 'string'/'number'/'boolean'.
  3. Build the object in JS and assign after the element is connected so Blazor picks it up via _supplyUpdatedParameters.

Example fix

// before
el.setAttribute('chartOptions', '{"legend":true}'); // throws

// after — assign as a property, the framework-defined setter handles it
el.chartOptions = { legend: true };
Defensive patterns

Strategy: type-guard

Validate before calling

// Route object-typed parameters to the property setter, never the attribute.
function setParam(el, name, value) {
  if (value !== null && typeof value === 'object') {
    el[camelCase(name)] = value; // framework-defined setter
  } else {
    el.setAttribute(dasherize(name), value);
  }
}

Type guard

function shouldUseProperty(value) {
  return value !== null && typeof value === 'object';
}

Try / catch

try {
  el.setAttribute(name, value);
} catch (e) {
  if (/cannot be set using an attribute/.test(e.message)) {
    el[camelCase(name)] = value;
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11). Data as JSON: /api/errors/75f99fc2175160e6. Report an issue: GitHub.

Appendix: source

Thrown at src/Components/CustomElements/src/js/BlazorCustomElements.ts:134

          case 'false':
          case 'False':
            return false;
          default:
            throw new Error(`Invalid boolean value '${attributeValue}' for parameter '${parameterName}'`);
        }
      case 'number':
        const number = Number(attributeValue);
        if (Number.isNaN(number)) {
          throw new Error(`Invalid number value '${attributeValue}' for parameter '${parameterName}'`);
        } else {
          return number;
        }
      case 'boolean?':
        return attributeValue ? BlazorCustomElement.parseAttributeValue(attributeValue, 'boolean', parameterName) : null;
      case 'number?':
        return attributeValue ? BlazorCustomElement.parseAttributeValue(attributeValue, 'number', parameterName) : null;
      case 'object':
        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.`);
      default:
        throw new Error(`Unknown type '${type}' for parameter '${parameterName}'`);
    }
  }
}

function dasherize(value: string): string {
  return camelCase(value).replace(/([A-Z])/g, "-$1").toLowerCase();
}

function camelCase(value: string): string {
  return value[0].toLowerCase() + value.substring(1);
}

interface JSComponentParameter {
  name: string;
  type: JSComponentParameterType;
}

View on GitHub (pinned to 3600ca084e)