handlebars-lang/handlebars.js · error · Exception
#if requires exactly one argument
Error message
#if requires exactly one argument
What it means
Handlebars' #if helper must receive exactly one conditional argument plus the compiled options object (arguments.length === 2). If the template supplies zero or more than one positional argument to #if, Handlebars throws this error at template-render time.
Source
Thrown at lib/handlebars/helpers/if.js:7
import { Exception } from '@handlebars/parser';
import { isEmpty, isFunction } from '../utils.js';
export default function (instance) {
instance.registerHelper('if', function (conditional, options) {
if (arguments.length != 2) {
throw new Exception('#if requires exactly one argument');
}
if (isFunction(conditional)) {
conditional = conditional.call(this);
}
// Default behavior is to render the positive path if the value is truthy and not empty.
// The `includeZero` option may be set to treat the conditional as purely not empty based on the
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
if ((!options.hash.includeZero && !conditional) || isEmpty(conditional)) {
return options.inverse(this);
} else {
return options.fn(this);
}
});
instance.registerHelper('unless', function (conditional, options) {
if (arguments.length != 2) {
throw new Exception('#unless requires exactly one argument');View on GitHub (pinned to 13a7a67991)
Solutions
- Ensure exactly one positional argument: {{#if value}}...{{/if}} — remove extras or move them to the hash: {{#if value key=val}}.
- Add the missing argument if #if was written bare.
- For multi-condition logic, combine in a registered helper or subexpression: {{#if (and a b)}} with an 'and' helper.
- When calling the helper programmatically, pass both arguments: if(value, {fn, inverse, hash}).
Example fix
// before
{{#if user.isAdmin extraArg}}...{{/if}}
// after
{{#if user.isAdmin}}...{{/if}} Defensive patterns
Strategy: validation
Validate before calling
// Pre-render validation of template usage (static check example)
const bad = /\{\{#if\s*(\}|[^}]+\s[^}\s]+\s+[^}\s]+\s*\})/.test(source);
if (bad) throw new Error('#if must have exactly one positional argument'); Type guard
function hasExactlyOneArg(conditional, options) {
return arguments.length === 2 && options && typeof options === 'object';
} Try / catch
try {
return template(data);
} catch (e) {
if (e.message.includes('#if requires exactly one argument')) {
console.error('Template #if has zero or multiple args; fix the template expression');
}
throw e;
} Prevention
- Always write {{#if value}} with exactly one positional argument
- Pass extra data via hash syntax (key=value), not positionals
- Combine complex conditions in registered helpers or subexpressions
- Add template linting to catch bare or multi-arg #if
- Test render all templates at build time to surface runtime errors early
When it happens
Trigger: {{#if}} with no argument (e.g. {{#if}}...{{/if}}); {{#if a b}} passing two positionals; calling instance.helpers.if(value) directly without options; a custom parser or whitespace/moustache syntax mistake merging arguments.
Common situations: Template typos after refactoring; concatenating template fragments so {{#if x}}{{/if}} loses its argument; passing extra positional args intending them as options — must use hash instead ({{#if x foo=bar}}); testing helpers directly without options.
Related errors
- #unless requires exactly one argument
- Invalid stack pop
- Must pass iterator to #each
- Missing helper: "${name}"
- #with requires exactly one argument
AI-assisted analysis of handlebars-lang/handlebars.js@13a7a67991 (2026-09-02).
Data as JSON: /api/errors/fa63db92fd39a0df.
Report an issue: GitHub.