emberjs/ember.js · error

You attempted to pass a path as argument (\`${arg.name}={{${

Error message

You attempted to pass a path as argument (\`${arg.name}={{${resolution.path}}}\`) but ${resolution.head} was not in scope. Try:\n* \`${arg.name}={{this.${resolution.path}}}\` if this is meant to be a property lookup, or\n* \`${arg.name}={{(${resolution.path})}}\` if this is meant to invoke the resolved helper, or\n* \`${arg.name}={{helper "${resolution.path}"}}\` if this is meant to pass the resolved helper by value

What it means

In strict-mode templates, a mutable `{{path}}` argument must resolve to something in scope (a local, `this` property, or known helper). When the path's head cannot be resolved, ElementNormalizer rejects the argument because it cannot tell whether you meant a property lookup, a helper invocation, or passing a helper by value.

Source

Thrown at packages/@glimmer/syntax/lib/v2/normalize.ts:757

    let { path } = value;

    if (path.type !== 'PathExpression') {
      return;
    }

    if (path.tail.length > 0) {
      return;
    }

    let resolution = this.ctx.resolutionFor(path, () => {
      // We deliberately don't want this to resolve anything. The purpose of
      // calling `resolutionFor` here is to check for strict mode, in-scope
      // local variables, etc.
      return null;
    });

    if (resolution.result === 'error' && resolution.path !== 'has-block') {
      throw generateSyntaxError(
        `You attempted to pass a path as argument (\`${arg.name}={{${resolution.path}}}\`) but ${resolution.head} was not in scope. Try:\n` +
          `* \`${arg.name}={{this.${resolution.path}}}\` if this is meant to be a property lookup, or\n` +
          `* \`${arg.name}={{(${resolution.path})}}\` if this is meant to invoke the resolved helper, or\n` +
          `* \`${arg.name}={{helper "${resolution.path}"}}\` if this is meant to pass the resolved helper by value`,
        arg.loc
      );
    }
  }

  private arg(arg: ASTv1.AttrNode): ASTv2.ComponentArg {
    assert(arg.name[0] === '@', 'An arg name must start with `@`');
    this.checkArgCall(arg);

    let offsets = this.ctx.loc(arg.loc);
    let nameSlice = offsets.sliceStartChars({ chars: arg.name.length }).toSlice(arg.name);
    let value = this.attrValue(arg.value);

    return this.ctx.builder.arg(

View on GitHub (pinned to 26f97246a8)

Solutions

  1. If it is a property lookup, change to `arg={{this.path}}` (or `@arg` / a declared local).
  2. If it is a helper, invoke it: `arg={{(path)}}` after importing/defining the helper in scope.
  3. To pass the helper itself by value, use `arg={{helper "path"}}`.
  4. If the value is a local (e.g. block param or `let` binding), check spelling and ensure it is actually in scope.

Example fix

// before (strict mode, `fullName` helper not in scope)
<UserCard name={{fullName}} />

// after (invoke the imported helper)
import { fullName } from '../helpers/full-name';
<UserCard name={{fullName this.user}} />
Defensive patterns

Strategy: validation

Validate before calling

// Before compiling, ensure every {{path}} arg head is in scope.
function isArgPathInScope(path, scope /* Set<string> of locals/imports */) {
  const head = path.split('.')[0];
  return head.startsWith('@') || head === 'this' || scope.has(head);
}

Prevention

When it happens

Trigger: Compiling a strict-mode template containing a component/helper invocation with an argument like `arg={{somePath}}` where `somePath` is not a declared local, not on `this`, and not a resolvable helper.

Common situations: Migrating a template from loose to strict mode (e.g. with `templateStrictMode` in Ember); forgetting `this.` before a property; referencing a helper that is not imported into the template scope; typos in local variable names.

Related errors


AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01). Data as JSON: /api/errors/3d0ea365887399bb. Report an issue: GitHub.