{"record":{"id":"a2773a25c7234a58","repo":"emberjs/ember.js","slug":"open-path-original-doesn-t-match-close","errorCode":null,"errorMessage":"${open.path.original} doesn't match ${close}","messagePattern":"(.+?) doesn't match (.+?)","errorType":"validation","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"packages/@handlebars/parser/lib/helpers.js","lineNumber":9,"sourceCode":"import Exception from './exception.js';\n\nfunction validateClose(open, close) {\n  close = close.path ? close.path.original : close;\n\n  if (open.path.original !== close) {\n    let errorNode = { loc: open.path.loc };\n\n    throw new Exception(open.path.original + \" doesn't match \" + close, errorNode);\n  }\n}\n\nexport function SourceLocation(source, locInfo) {\n  this.source = source;\n  this.start = {\n    line: locInfo.first_line,\n    column: locInfo.first_column,\n  };\n  this.end = {\n    line: locInfo.last_line,\n    column: locInfo.last_column,\n  };\n}\n\nexport function id(token) {\n  if (/^\\[.*\\]$/.test(token)) {\n    return token.substring(1, token.length - 1);","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@handlebars/parser/lib/helpers.js#L1-L27","documentation":"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.","triggerScenarios":"A template contains mismatched block tags: opening {{#foo}} and closing {{/bar}}, or closing {{#each}} with {{/with}}, including nested blocks closed in the wrong order.","commonSituations":"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.","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"],"exampleFix":"// before\n{{#each items}}\n  {{name}}\n{{/with}}\n// after\n{{#each items}}\n  {{name}}\n{{/each}}","handlingStrategy":"validation","validationCode":"// pre-parse template lint to catch mismatches\nconst opens = [...template.matchAll(/{{#(\\w+)/g)].map(m => m[1]);\nconst closes = [...template.matchAll(/{{\\/(\\w+)/g)].map(m => m[1]);\nconst matches = opens.length === closes.length && opens.slice().sort().join() === closes.slice().sort().join();","typeGuard":null,"tryCatchPattern":"try { template = parse(src); } catch (e) { if (/doesn't match/.test(e.message)) { reportSyntaxError(src, e.loc, e.message); } throw e; }","preventionTips":["Use an editor with Handlebars syntax highlighting","Lint templates in CI (ember-template-lint)","Rename open and close tags together via multi-cursor edits"],"tags":["template","handlebars","parser","syntax"],"backgroundTag":"block-tag-mismatch","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}