dotnet/aspnetcore · error · Error

The parameter '${parameterName}' accepts a complex-typed obj

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 unconditionally by parseAttributeValue in the 'object' case. Complex-typed (object) parameters cannot be expressed as a string attribute, so the framework refuses to parse them; the only way to supply such a parameter is via the element's JS property, which is defined in the constructor for each mapped parameter.

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 294cab2f9b)

Solutions

  1. Set the value as a JS property: const el = document.querySelector('my-component'); el.data = { a: 1 }; — the constructor wires up a property setter per parameter (BlazorCustomElements.ts:50-65).
  2. Redesign the parameter as a primitive (string JSON) and parse it inside the component, if you must use an attribute.
  3. Split the complex parameter into multiple primitive [Parameter] properties that can each be set as attributes.

Example fix

// before (throws)
<my-chart options="{\"legend\":true}"></my-chart>

// after
const chart = document.querySelector('my-chart');
chart.options = { legend: true };
Defensive patterns

Strategy: type-guard

Validate before calling

function isComplexParamType(type: string): boolean {
  return type === 'object';
}

// for each descriptor, decide attribute vs property
for (const p of parameterDescriptors) {
  if (isComplexParamType(p.type)) {
    el[p.name] = complexValue; // property, not attribute
  } else {
    el.setAttribute(dasherize(p.name), String(value));
  }
}

Type guard

type ComplexType = 'object';
function isObjectParam(p: { type: string }): p is { type: ComplexType } {
  return p.type === 'object';
}

Try / catch

try {
  el.setAttribute('options', JSON.stringify(value));
} catch (e) {
  if (/cannot be set using an attribute/.test((e as Error).message)) {
    el.options = value; // fall back to property
  } else throw e;
}

Prevention

When it happens

Trigger: Declaring a [Parameter] of a complex type (class, array, nested object) on a Razor component exposed as a custom element, and then trying to set it via an HTML attribute: <my-component data="{a:1}"/>. The framework detects type 'object' and throws.

Common situations: Components that take POCOs, lists, dictionaries, or component references as parameters and are registered via RegisterAsCustomElement. Authors naturally try attribute binding first and hit this.

Related errors


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