emberjs/ember.js · error · Exception
${open.path.original} doesn't match ${close}
Error message
${open.path.original} doesn't match ${close} What it means
The Handlebars parser validates that a closing block/partial-block tag matches the tag that opened it (e.g. {{#if}} ... {{/unless}}). When the open and close path names differ, validateClose throws with both names so you can find the mismatch in the template.
Source
Thrown at packages/@handlebars/parser/lib/helpers.js:9
import Exception from './exception.js';
function validateClose(open, close) {
close = close.path ? close.path.original : close;
if (open.path.original !== close) {
let errorNode = { loc: open.path.loc };
throw new Exception(open.path.original + " doesn't match " + close, errorNode);
}
}
export function SourceLocation(source, locInfo) {
this.source = source;
this.start = {
line: locInfo.first_line,
column: locInfo.first_column,
};
this.end = {
line: locInfo.last_line,
column: locInfo.last_column,
};
}
export function id(token) {
if (/^\[.*\]$/.test(token)) {
return token.substring(1, token.length - 1);View on GitHub (pinned to 26f97246a8)
Solutions
- Make the close tag exactly match the open tag: {{#if x}} ... {{/if}}
- Check nesting order — inner blocks must close before outer ones
- Use an editor with Handlebars syntax highlighting/bracket matching to locate the mismatch
- If the name is legitimately different, restructure to separate sibling blocks
Example fix
// before
{{#each items}}
{{name}}
{{/with}}
// after
{{#each items}}
{{name}}
{{/each}} Defensive patterns
Strategy: validation
Validate before calling
// pre-parse template lint to catch mismatches
const opens = [...template.matchAll(/{{#(\w+)/g)].map(m => m[1]);
const closes = [...template.matchAll(/{{\/(\w+)/g)].map(m => m[1]);
const matches = opens.length === closes.length && opens.slice().sort().join() === closes.slice().sort().join(); Try / catch
try { template = parse(src); } catch (e) { if (/doesn't match/.test(e.message)) { reportSyntaxError(src, e.loc, e.message); } throw e; } Prevention
- Use an editor with Handlebars syntax highlighting
- Lint templates in CI (ember-template-lint)
- Rename open and close tags together via multi-cursor edits
When it happens
Trigger: A template contains mismatched block tags: opening {{#foo}} and closing {{/bar}}, or closing {{#each}} with {{/with}}, including nested blocks closed in the wrong order.
Common situations: Hand-edited templates; copy/paste leaving a stale close tag; renamed a helper in the open tag but not the close; mismatched indentation hiding the real pairing.
Related errors
- Invalid path: ${original}
- Compile Error: ${error.problem} @ ${error.span.start}..${err
- Compile Error: ${template.problem} @ ${template.span.start}.
- Unexpected inverse block on decorator
- b.concat requires at least one part
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/a2773a25c7234a58.
Report an issue: GitHub.