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
- Remove the unsupported named argument from the `on` modifier usage.
- If it was a typo, correct it to one of `once`, `passive`, or `capture`.
- If you need to pass extra data to the handler, wrap the callback with the `fn` helper: {{on "click" (fn this.handler arg)}}.
- 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
- Only ever pass once/passive/capture as named args to {{on}}.
- Use {{fn}} for extra handler arguments, never extra named args.
- Add an eslint-plugin-ember/template lint to flag unknown modifier args.
- Review on-modifier usages when migrating from classic event handling.
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
- Compile Error: ${template.problem} @ ${template.span.start}.
- You marked this listener as 'passive', meaning that you must
- Attempted to resolve a dynamic component with a string defin
- A resolved helper cannot be passed as a named argument as th
- deprecation override for ${id} not found
AI-assisted analysis of emberjs/ember.js@26f97246a8 (2026-09-01).
Data as JSON: /api/errors/144ae5e5349ff10d.
Report an issue: GitHub.