emberjs/ember.js · error
Invalid block parameters syntax: invalid identifier name \`$
Error message
Invalid block parameters syntax: invalid identifier name \`${state.name}\` What it means
A collected block param identifier is invalid: it is either `this` (which cannot be a block param name) or matches characters not allowed in Handlebars identifiers (checked via ID_INVERSE_PATTERN). The parser validates each identifier when it hits a pipe or space that terminates it.
Source
Thrown at packages/@glimmer/syntax/lib/parser/tokenizer-event-handlers.ts:471
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 === '|' || isSpace(next)) {
let loc = state.start.until(this.offset());
if (state.name === 'this' || ID_INVERSE_PATTERN.test(state.name)) {
throw generateSyntaxError(
`Invalid block parameters syntax: invalid identifier name \`${state.name}\``,
loc
);
}
element.params.push(b.var({ name: state.name, loc }));
state = next === '|' ? { state: 'AfterEndPipe' } : { state: 'BeforeBlockParamName' };
this.tokenizer.consume();
} else if (next === '>' || next === '/') {
throw generateSyntaxError(
`Invalid block parameters syntax: expecting "|" but the tag was closed prematurely`,
as.start.until(this.offset().move(1))
);
} else {
// slurp up anything else into the name, validate later
state.name += next;
this.tokenizer.consume();View on GitHub (pinned to 26f97246a8)
Solutions
- Rename the param to a valid Handlebars identifier (letters, digits, underscore, non-leading dash per handlebars ID rules)
- Never use `this` as a block param name; pick a distinct name
Example fix
// before
<Foo as |this|>{{this}}</Foo>
// after
<Foo as |value|>{{value}}</Foo> Defensive patterns
Strategy: validation
Validate before calling
// Validate each block param name against Handlebars ID rules
const ID_INVERSE = /[!"#%&'()*+,./;<=>@[\]^`{|}~]/;
for (const m of template.matchAll(/as\s+\|([^|]*)\|/g)) {
for (const name of m[1].trim().split(/\s+/)) {
if (name === 'this' || ID_INVERSE.test(name)) {
throw new Error(`Invalid block param name: ${name}`);
}
}
} Prevention
- Never use `this` as a block param name
- Stick to simple identifiers (letters, digits, underscore) for params
When it happens
Trigger: parsePossibleBlockParams (via appendToAttributeName) when a param name is terminated by `|` or whitespace and state.name === 'this' or ID_INVERSE_PATTERN.test(state.name) passes — e.g. `<Foo as |this|>`, `<Foo as |a-b!|>`.
Common situations: Trying to shadow `this`; using dashes-plus-invalid characters, unicode, or punctuation in param names; typos like `as |my param!|`.
Related errors
- Invalid block parameters syntax: block parameters must be pr
- Invalid block parameters syntax: expecting at least one spac
- Invalid block parameters syntax: mustaches cannot be used in
- Invalid block parameters syntax: expecting the tag to be clo
- Invalid block parameters syntax: empty parameters list, expe
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/7a8e0252a0b34a7d.
Report an issue: GitHub.