emberjs/ember.js · error

Invalid block parameters syntax: mustaches cannot be used in

Error message

Invalid block parameters syntax: mustaches cannot be used inside parameters list

What it means

While the parser is inside a block parameters list (`as |...|`), a mustache (`{{...}}`) cannot legally appear; block params are plain identifiers only. When the HTML tokenizer encounters a mustache in that state, the parser throws this error at the mustache's location.

Source

Thrown at packages/@glimmer/syntax/lib/parser/tokenizer-event-handlers.ts:406

        } else {
          // " as {{...", " as bs...", " as =...", " as ...", " as/>..."
          // Don't consume, let the normal tokenizer code handle the next steps
          state = { state: 'Done' };
        }
      },

      BeforeBlockParamName: (next: string) => {
        assert(state.state === 'BeforeBlockParamName', 'bug in block params parser');

        if (isSpace(next)) {
          this.tokenizer.consume();
        } else if (next === '') {
          // The HTML tokenizer ran out of characters, so we are either
          // encountering mustache or <EOF>
          state = { state: 'Done' };
          this.pendingError = {
            mustache(loc: src.SourceSpan) {
              throw generateSyntaxError(
                `Invalid block parameters syntax: mustaches cannot be used inside parameters list`,
                loc
              );
            },
            eof(loc: src.SourceOffset) {
              throw generateSyntaxError(
                `Invalid block parameters syntax: expecting the tag to be closed with ">" or "/>" after parameters list`,
                as.start.until(loc)
              );
            },
          };
        } else if (next === '|') {
          if (element.params.length === 0) {
            // Following Handlebars and treat empty block params a syntax error
            throw generateSyntaxError(
              `Invalid block parameters syntax: empty parameters list, expecting at least one identifier`,
              as.start.until(this.offset().move(1))
            );

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Use plain identifiers only inside the pipes; bind values via the yielded block, not mustaches
  2. Close the parameters list with `|` before any mustache expression

Example fix

// before
<Foo as |a {{b}}|>{{a}}</Foo>
// after
<Foo as |a|>{{a}} {{b}}</Foo>
Defensive patterns

Strategy: validation

Validate before calling

// Block param lists may only contain identifiers
if (/<[^>]*\bas\s\|[^|]*\{\{/.test(template)) {
  throw new Error('Mustaches are not allowed inside a block params list');
}

Prevention

When it happens

Trigger: mustache() handler firing while parsePossibleBlockParams is active and the parser is mid-parameters-list — e.g. `<Foo as |a {{b}}|>` or `<Foo as |{{x}}|>`.

Common situations: Trying to interpolate a dynamic name into block params; typos like `<Foo as |a|{{b}}>` where the pipe list was left unclosed before a mustache.

Related errors


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