handlebars-lang/handlebars.js · error · Exception
#unless requires exactly one argument
Error message
#unless requires exactly one argument
What it means
Handlebars' #unless helper is the inverse of #if and likewise requires exactly one conditional argument plus the options object. The error is thrown at render time when #unless is given zero or multiple positional arguments, before delegating to the 'if' helper with swapped fn/inverse blocks.
Source
Thrown at lib/handlebars/helpers/if.js:25
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');
}
return instance.helpers['if'].call(this, conditional, {
fn: options.inverse,
inverse: options.fn,
hash: options.hash,
});
});
}
View on GitHub (pinned to 13a7a67991)
Solutions
- Use exactly one argument: {{#unless value}}...{{/unless}}; remove extra positionals or convert them to hash pairs ({{#unless value key=val}}).
- Add the missing conditional if #unless was left bare.
- For compound conditions, wrap in a subexpression helper: {{#unless (or a b)}}.
- When invoking programmatically, pass options: unless(value, {fn, inverse, hash}).
Example fix
// before
{{#unless}}...{{/unless}}
// after
{{#unless user.isBlocked}}...{{/unless}} Defensive patterns
Strategy: validation
Validate before calling
// Pre-render validation: #unless must take exactly one positional argument
const bad = /\{\{#unless\s*(\}|[^}]+\s[^}\s]+\s+[^}\s]+\s*\})/.test(source);
if (bad) throw new Error('#unless 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('#unless requires exactly one argument')) {
console.error('Template #unless has zero or multiple args; fix the template expression');
}
throw e;
} Prevention
- Write {{#unless value}} with exactly one positional argument
- Convert extra arguments to hash pairs (key=value)
- Use subexpression helpers like (or a b) for compound conditions
- Lint templates for malformed #unless expressions
- Render every template once in CI tests to catch these at build time
When it happens
Trigger: {{#unless}} with no argument; {{#unless a b}} with two positionals; calling instance.helpers.unless(value) directly without options; template assembly/parse quirks merging tokens so extra args end up on #unless.
Common situations: Copy-pasted templates where an argument was accidentally deleted or duplicated; upgrading or auto-formatting templates that mangled the mustache expression; direct helper invocation in tests missing the options object.
Related errors
- #if 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/bafdb76c1c65bcbc.
Report an issue: GitHub.