emberjs/ember.js · error · Exception
Unexpected inverse block on decorator
Error message
Unexpected inverse block on decorator
What it means
Decorators are metadata-only Handlebars nodes and cannot have an inverse ({{else}}) branch. When prepareBlock builds a decorator block and finds an inverse/else program attached, it throws because the construct is meaningless in Handlebars semantics.
Source
Thrown at packages/@handlebars/parser/lib/helpers.js:151
closeStrip: {},
loc: locInfo,
};
}
export function prepareBlock(openBlock, program, inverseAndProgram, close, inverted, locInfo) {
if (close && close.path) {
validateClose(openBlock, close);
}
let decorator = /\*/.test(openBlock.open);
program.blockParams = openBlock.blockParams;
let inverse, inverseStrip;
if (inverseAndProgram) {
if (decorator) {
throw new Exception('Unexpected inverse block on decorator', inverseAndProgram);
}
if (inverseAndProgram.chain) {
inverseAndProgram.program.body[0].closeStrip = close.strip;
}
inverseStrip = inverseAndProgram.strip;
inverse = inverseAndProgram.program;
}
if (inverted) {
inverted = inverse;
inverse = program;
program = inverted;
}
return {
type: decorator ? 'DecoratorBlock' : 'BlockStatement',View on GitHub (pinned to 26f97246a8)
Solutions
- Remove the {{else}} branch from the decorator block
- Convert the construct to a regular block helper if you need inverse behavior
- Review template codegen/transform steps that wrap decorators in block syntax
Example fix
// before
{{#my-decorator}}
main
{{else}}
fallback
{{/my-decorator}}
// after
{{my-decorator}}
{{#if fallbackNeeded}}fallback{{/if}} Defensive patterns
Strategy: validation
Validate before calling
// reject decorator blocks with else before parse
if (/{{\s*[#~][^}]*}}[\s\S]*{{\s*else/.test(src)) reviewTemplate(src); Try / catch
try { parse(src); } catch (e) { if (/inverse block on decorator/.test(e.message)) { stripElseBranch(src); } throw e; } Prevention
- Don't attach {{else}} to decorators or metadata blocks
- Generate templates programmatically with a validated AST builder
- Lint templates with ember-template-lint
When it happens
Trigger: A template attaches an {{else}} to a decorator, e.g. {{#my-decorator}}...{{else}}...{{/my-decorator}} where my-decorator was parsed as a decorator (double-curlies with ~ or decorator registration context).
Common situations: Confusing decorators with block helpers; copy-pasted block syntax around a decorator; generated templates emitted with else branches for decorator nodes.
Related errors
- ${open.path.original} doesn't match ${close}
- Invalid path: ${original}
- Compile Error: ${error.problem} @ ${error.span.start}..${err
- Compile Error: ${template.problem} @ ${template.span.start}.
- Unexpected node type "${value.type}" found when accepting ${
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/f8c2899c44adf06e.
Report an issue: GitHub.