emberjs/ember.js · error

Unexpected block params in <${name.chars}>: simple elements

Error message

Unexpected block params in <${name.chars}>: simple elements cannot have block params

What it means

Glimmer's template normalizer builds ASTv2 SimpleElementNode for plain HTML tags like <div>. If a tag has block params (e.g. <div as |x|>) but its name is not recognized as a component invocation, it cannot yield anything, so the compiler rejects the template rather than silently dropping the params.

Source

Thrown at packages/@glimmer/syntax/lib/v2/normalize.ts:974

    ) {
      throw generateSyntaxError(
        `named block <:${name.chars}> cannot have attributes, arguments, or modifiers`,
        this.loc
      );
    }

    let offsets = SpanList.range(this.nonBlockChildren, this.loc);

    return this.block.builder.namedBlock(
      name,
      this.block.builder.block(table, this.nonBlockChildren, offsets),
      this.loc
    );
  }

  assertElement(name: SourceSlice, hasBlockParams: boolean): ASTv2.SimpleElement {
    if (hasBlockParams) {
      throw generateSyntaxError(
        `Unexpected block params in <${name.chars}>: simple elements cannot have block params`,
        this.loc
      );
    }

    if (isPresentArray(this.namedBlocks)) {
      let names = this.namedBlocks.map((b) => b.name);

      if (names.length === 1) {
        throw generateSyntaxError(
          `Unexpected named block <:foo> inside <${name.chars}> HTML element`,
          this.loc
        );
      } else {
        let printedNames = names.map((n) => `<:${n.chars}>`).join(', ');
        throw generateSyntaxError(
          `Unexpected named blocks inside <${name.chars}> HTML element (${printedNames})`,
          this.loc

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Remove the `as |...|` block params from the element tag
  2. If the tag was meant to be a component, rename it to a valid component name (capitalized or namespaced, e.g. <MyThing> or <MyThing::Row>)
  3. Check that the component exists/resolves where it is invoked

Example fix

// before
<div as |item|>
  <li>{{item}}</li>
</div>
// after
<div>
  {{#each items as |item|}}
    <li>{{item}}</li>
  {{/each}}
</div>
Defensive patterns

Strategy: validation

Validate before calling

function isBlockParamsOnElement(tag) {
  return /^[a-z]/.test(tag) && /\s+as\s+\|/.test(tag);
}
// lint templates before build: strip `as |...|` from any tag starting lowercase

Prevention

When it happens

Trigger: Compiling a template where an HTML element tag is written with block params, e.g. <div as |item|>...</div> — the parser sees |params| on a tag that resolves to a simple element.

Common situations: Typos in component names (lowercased or misspelled so angle-bracket resolution falls back to element), renaming a component so the old tag becomes an unknown element, or accidentally copying `as |x|` syntax onto a plain element.

Related errors


AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01). Data as JSON: /api/errors/ca924c3942296da6. Report an issue: GitHub.