emberjs/ember.js · error

Unexpected named block <:foo> inside <${name.chars}> HTML el

Error message

Unexpected named block <:foo> inside <${name.chars}> HTML element

What it means

In ASTv2 normalization, an HTML element (a tag that is not a component invocation) may not contain named blocks like <:default>, <:header> or <:foo>. Named blocks are only meaningful when invoking a component, so a single named block inside an HTML element is a syntax error.

Source

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

      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
        );
      }
    }

    return this.el.simple(name, this.nonBlockChildren, this.loc);
  }

  assertComponent(
    name: string,
    table: BlockSymbolTable,

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Remove the named block from inside the HTML element
  2. Move the named block into a component invocation tag instead
  3. Replace the named block with normal element content or {{yield}} inside a component template

Example fix

// before
<div>
  <:foo>hello</:foo>
</div>
// after
<div>hello</div>
Defensive patterns

Strategy: validation

Validate before calling

function hasNamedBlockInHtmlElement(template) {
  return /<[a-z][^>]*>[\s\S]*<:\w+>/.test(template);
}

Prevention

When it happens

Trigger: Compiling a template with exactly one named block inside a plain HTML element, e.g. <div><:foo>content</:foo></div> — the normalizer's assertElement path sees namedBlocks present on a SimpleElement.

Common situations: Accidentally writing <:yield>-style blocks inside plain tags, confusing named blocks with the {{yield}} helper, or copy-pasting component invocation markup into element markup.

Related errors


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