{"record":{"id":"8a27a3adb116a2b9","repo":"handlebars-lang/handlebars.js","slug":"must-pass-iterator-to-each","errorCode":null,"errorMessage":"Must pass iterator to #each","messagePattern":"Must pass iterator to #each","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"lib/handlebars/helpers/each.js","lineNumber":7,"sourceCode":"import { Exception } from '@handlebars/parser';\nimport { createFrame, isArray, isFunction, isMap, isSet } from '../utils.js';\n\nexport default function (instance) {\n  instance.registerHelper('each', function (context, options) {\n    if (!options) {\n      throw new Exception('Must pass iterator to #each');\n    }\n\n    let fn = options.fn,\n      inverse = options.inverse,\n      i = 0,\n      ret = '',\n      data;\n\n    if (isFunction(context)) {\n      context = context.call(this);\n    }\n\n    if (options.data) {\n      data = createFrame(options.data);\n    }\n\n    function execIteration(field, value, index, last) {\n      if (data) {","sourceCodeStart":1,"sourceCodeEnd":25,"githubUrl":"https://github.com/handlebars-lang/handlebars.js/blob/13a7a679910d2adbfe7f6fad61ce8f98426b0378/lib/handlebars/helpers/each.js#L1-L25","documentation":"Handlebars' built-in #each helper requires an options object (the compiled block containing options.fn and options.inverse). This error is thrown when #each is invoked without that second argument — i.e. the helper was called programmatically or as a plain helper without a block. In templates this normally only happens via handlebars.callHelper-style misuse or partials invoking helpers manually.","triggerScenarios":"Calling instance.helpers.each(context) directly with no options argument; invoking the helper via hbs.helpers.each in a unit test without passing {fn, inverse, hash}; template AST referencing {{each}} where the parser couldn't attach a block (custom parser/misuse); using helperMissing-style invocation where options got dropped.","commonSituations":"Unit-testing custom helpers by calling Handlebars.helpers.each directly; migrating from older Handlebars versions where helper invocation signatures differed; wrapping #each in a custom helper but forgetting to forward options.","solutions":["Always pass the options object when calling the each helper programmatically: each(context, options) with options containing fn/inverse/hash.","In a custom wrapper helper, forward the options argument: return instance.helpers.each.call(this, context, options).","In templates, ensure #each is written as a block helper: {{#each items}}...{{/each}}, not a bare {{each}}.","In tests, build a minimal options object: each(items, {fn: item => item, inverse: () => ''})."],"exampleFix":"// before\nHandlebars.helpers.each(items);\n// after\nHandlebars.helpers.each(items, { fn: item => item, inverse: () => '', hash: {} });","handlingStrategy":"validation","validationCode":"function safeEach(instance, context, options) {\n  if (!options || typeof options.fn !== 'function') {\n    throw new TypeError('safeEach requires options with fn (block)');\n  }\n  return instance.helpers.each.call(this, context, options);\n}","typeGuard":"function hasEachOptions(options) {\n  return options != null && typeof options === 'object' && typeof options.fn === 'function';\n}","tryCatchPattern":"try {\n  return Handlebars.helpers.each(items, options);\n} catch (e) {\n  if (e.message.includes('Must pass iterator to #each')) {\n    console.error('each invoked without block options; pass {fn, inverse, hash}');\n  }\n  throw e;\n}","preventionTips":["Never call helpers directly without forwarding the options argument","In wrapper helpers, always pass options through unchanged","Write #each as a block helper {{#each x}}...{{/each}} in templates","In tests, construct a minimal options object with fn and inverse","Lint templates for bare {{each}} references"],"tags":["handlebars","each-helper","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"13a7a679910d2adbfe7f6fad61ce8f98426b0378","analyzedAt":"2026-09-02T20:25:07.518Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}