emberjs/ember.js · error

Unexpected named blocks inside <${name.chars}> HTML element

Error message

Unexpected named blocks inside <${name.chars}> HTML element (${printedNames})

What it means

Same rule as the single-named-block case: plain HTML elements cannot contain any named blocks. When more than one named block (<:a>, <:b>, ...) appears inside an HTML element, the compiler reports all offending block names to help locate the mistake.

Source

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

  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,
    hasBlockParams: boolean
  ): PresentArray<ASTv2.NamedBlock> {
    if (isPresentArray(this.namedBlocks) && this.hasSemanticContent) {
      throw generateSyntaxError(
        `Unexpected content inside <${name}> component invocation: when using named blocks, the tag cannot contain other content`,
        this.loc

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Convert the tag to a component invocation if blocks are intended (capitalize/namespace the name)
  2. Remove the named blocks and put content directly inside the element
  3. Split content into multiple elements instead of named blocks

Example fix

// before
<section>
  <:header>Title</:header>
  <:body>Content</:body>
</section>
// after
<Section>
  <:header>Title</:header>
  <:body>Content</:body>
</Section>
Defensive patterns

Strategy: validation

Validate before calling

function hasMultipleNamedBlocksInElement(template) {
  const m = template.match(/<:\w+>/g) || [];
  return m.length > 1;
}

Prevention

When it happens

Trigger: Compiling a template with two or more named blocks inside a plain HTML element, e.g. <div><:a>x</:a><:b>y</:b></div> — assertElement builds printedNames from the block names and throws.

Common situations: Mistaking an HTML tag for a component invocation (e.g. writing <ul> instead of <Ul> or <MyList>), or authoring wrapper markup by hand that mimics yieldable component syntax.

Related errors


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