emberjs/ember.js · error · Error

You can only `once`, `passive` or `capture` named arguments

Error message

You can only `once`, `passive` or `capture` named arguments to the `on` modifier, but you provided ${Object.keys(extra).join(', ')} on ${selector}

What it means

The `on` element modifier only accepts three named options: `once`, `passive`, and `capture`, all booleans. During render (in DEBUG builds), updateListener reifies the named args and throws if any other named key is present, listing the offending key names and the element's selector.

Source

Thrown at packages/@glimmer/runtime/lib/modifiers/on.ts:138

        }`;
      });

      passive = check(_passive, CheckOr(CheckBoolean, CheckUndefined), (actual) => {
        return `You must pass a boolean or undefined as the \`passive\` argument to the \`on\` modifier; you passed ${actual}. While rendering:\n\n${
          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
          args.named['passive']!.debugLabel ?? `{unlabeled value}`
        }`;
      });

      capture = check(_capture, CheckOr(CheckBoolean, CheckUndefined), (actual) => {
        return `You must pass a boolean or undefined as the \`capture\` argument to the \`on\` modifier; you passed ${actual}. While rendering:\n\n${
          // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
          args.named['capture']!.debugLabel ?? `{unlabeled value}`
        }`;
      });

      if (Object.keys(extra).length > 0) {
        throw new Error(
          `You can only \`once\`, \`passive\` or \`capture\` named arguments to the \`on\` modifier, but you provided ${Object.keys(
            extra
          ).join(', ')} on ${selector}`
        );
      }
    } else {
      let { once: _once, passive: _passive, capture: _capture } = args.named;

      if (_once) {
        once = valueForRef(_once) as boolean | undefined;
      }

      if (_passive) {
        passive = valueForRef(_passive) as boolean | undefined;
      }

      if (_capture) {
        capture = valueForRef(_capture) as boolean | undefined;

View on GitHub (pinned to 26f97246a8)

Solutions

  1. Remove the unsupported named argument from the `on` modifier usage.
  2. If it was a typo, correct it to one of `once`, `passive`, or `capture`.
  3. If you need to pass extra data to the handler, wrap the callback with the `fn` helper: {{on "click" (fn this.handler arg)}}.
  4. Handle behaviors like preventDefault inside the callback body, not as a modifier option.

Example fix

<!-- before -->
<button {{on "click" this.save preventDefault=true}}>Save</button>

<!-- after -->
<button {{on "click" this.save}}>Save</button>

// this.save
save(event) {
  event.preventDefault();
  // ...
}
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['once', 'passive', 'capture'];
function checkOnOptions(named = {}) {
  const extra = Object.keys(named).filter((k) => !ALLOWED.includes(k));
  if (extra.length) throw new Error(`Invalid 'on' modifier options: ${extra.join(', ')}`);
}
// template lint rule alternative:
// {{on "click" this.handler once=true}} -> validate named args before render

Type guard

function isOnModifierOptions(v) {
  return v != null && Object.keys(v).every((k) => ['once', 'passive', 'capture'].includes(k));
}

Prevention

When it happens

Trigger: Calling the `on` modifier in a template with any named argument other than once/passive/capture, e.g. {{on "click" this.handler stopPropagation=true}} or a typo like {{on "click" this.haner onces=true}}. Thrown at install or update of the modifier.

Common situations: Migrating from other event-handling patterns where users expect options like `preventDefault` or `debounce`; typos in option names; passing extra data as named args instead of using the `fn` helper.

Related errors


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