{"record":{"id":"d9239923e6dc9a80","repo":"emberjs/ember.js","slug":"changing-context-using-is-not-supported-in-g","errorCode":null,"errorMessage":"Changing context using \"../\" is not supported in Glimmer","messagePattern":"Changing context using \"\\.\\./\" is not supported in Glimmer","errorType":"validation","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/@glimmer/syntax/lib/parser/handlebars-node-visitors.ts","lineNumber":405,"sourceCode":"\n  SubExpression(sexpr: HBS.SubExpression): ASTv1.SubExpression {\n    const { path, params, hash } = acceptCallNodes(this, sexpr);\n    return b.sexpr({ path, params, hash, loc: this.source.spanFor(sexpr.loc) });\n  }\n\n  PathExpression(path: HBS.PathExpression): ASTv1.PathExpression {\n    const { original } = path;\n    let parts: string[];\n\n    if (original.indexOf('/') !== -1) {\n      if (original.slice(0, 2) === './') {\n        throw generateSyntaxError(\n          `Using \"./\" is not supported in Glimmer and unnecessary`,\n          this.source.spanFor(path.loc)\n        );\n      }\n      if (original.slice(0, 3) === '../') {\n        throw generateSyntaxError(\n          `Changing context using \"../\" is not supported in Glimmer`,\n          this.source.spanFor(path.loc)\n        );\n      }\n      if (original.indexOf('.') !== -1) {\n        throw generateSyntaxError(\n          `Mixing '.' and '/' in paths is not supported in Glimmer; use only '.' to separate property paths`,\n          this.source.spanFor(path.loc)\n        );\n      }\n      parts = [path.parts.join('/')];\n    } else if (original === '.') {\n      throw generateSyntaxError(\n        `'.' is not a supported path in Glimmer; check for a path with a trailing '.'`,\n        this.source.spanFor(path.loc)\n      );\n    } else {\n      parts = path.parts;","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/syntax/lib/parser/handlebars-node-visitors.ts#L387-L423","documentation":"Glimmer's Handlebars parser rejects path expressions that begin with '../' because Glimmer templates have a single, flat scope: dynamic context switching via relative paths was an Ember-Classic (curly component / pre-Glimmer) behavior that no longer exists. The parser inspects every PathExpression's original string during handlebars-node-visitors traversal and throws a syntax error with the offending path's source span.","triggerScenarios":"Any template compiled with @glimmer/syntax (e.g. via Ember's template compiler) containing a path expression whose original string starts with '../', such as {{../foo}}, {{../item.name}}, or (../parentHelper arg). The check runs in the PathExpression visitor when original.slice(0,3) === '../'.","commonSituations":"Migrating legacy Ember (pre-Octane / pre-Glimmer) templates to modern Glimmer; copying patterns from old blog posts using contextual components or itemController-era relative paths; nested each/if blocks that relied on ../ to reach an outer scope's variable instead of using block params.","solutions":["Rewrite the path to reference the value directly via a block param or local variable instead of the parent context (e.g. wrap the each in {{each items as |item|}} and use {{item.name}}).","Bind the needed outer value to a local: {{#let this.parent as |parent|}} ... {{parent.x}} {{/let}}, or pass it down as an argument/component prop.","Use a helper or getter in the backing class to expose the outer-scope value instead of reaching up the context stack.","If this is a generated/legacy template, update the code generator so it no longer emits '../' paths."],"exampleFix":"// before\n{{#each items}}\n  {{title}} of {{../sectionName}}\n{{/each}}\n\n// after\n{{#each items as |item|}}\n  {{item.title}} of {{this.sectionName}}\n{{/each}}","handlingStrategy":"validation","validationCode":"// before compiling a template\nfunction assertNoRelativePaths(template) {\n  const offenders = template.match(/\\.\\.\\/[^\\s}]+/g);\n  if (offenders) throw new Error(`Relative '../' paths not allowed: ${offenders.join(', ')}`);\n}\nassertNoRelativePaths(template);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use block params ({{#each list as |item|}}) instead of ../ to access outer scope","Use {{#let}} to bind outer values to locals in nested scopes","Enable ember-template-lint rule 'no-implicit-this' and related path rules in CI","When migrating old Ember templates, grep for '../' before compiling"],"tags":["glimmer","handlebars","template-syntax","scope-resolution"],"backgroundTag":"glimmer-relative-path-not-supported","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}