{"record":{"id":"555a261c973cd554","repo":"handlebars-lang/handlebars.js","slug":"you-specified-knownhelpersonly-but-used-the-unkno","errorCode":null,"errorMessage":"You specified knownHelpersOnly, but used the unknown helper ${name}","messagePattern":"You specified knownHelpersOnly, but used the unknown helper (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"lib/handlebars/compiler/compiler.js","lineNumber":268,"sourceCode":"    this.opcode('invokeAmbiguous', name, isBlock);\n  },\n\n  simpleSexpr: function (sexpr) {\n    let path = sexpr.path;\n    path.strict = true;\n    this.accept(path);\n    this.opcode('resolvePossibleLambda');\n  },\n\n  helperSexpr: function (sexpr, program, inverse) {\n    let params = this.setupFullMustacheParams(sexpr, program, inverse),\n      path = sexpr.path,\n      name = path.parts[0];\n\n    if (this.options.knownHelpers[name]) {\n      this.opcode('invokeKnownHelper', params.length, name);\n    } else if (this.options.knownHelpersOnly) {\n      throw new Exception(\n        'You specified knownHelpersOnly, but used the unknown helper ' + name,\n        sexpr\n      );\n    } else {\n      path.strict = true;\n      path.falsy = true;\n\n      this.accept(path);\n      this.opcode(\n        'invokeHelper',\n        params.length,\n        path.original,\n        AST.helpers.simpleId(path)\n      );\n    }\n  },\n\n  PathExpression: function (path) {","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/handlebars-lang/handlebars.js/blob/13a7a679910d2adbfe7f6fad61ce8f98426b0378/lib/handlebars/compiler/compiler.js#L250-L286","documentation":"With the compiler option knownHelpersOnly:true, any subexpression/ Mustache referencing a helper not listed in options.knownHelpers is rejected at compile time. This enables optimized codegen but requires a complete helper whitelist.","triggerScenarios":"Handlebars.compile(tpl, {knownHelpersOnly: true, knownHelpers: {foo: true}}) on a template using a helper (e.g. {{bar}}) absent from knownHelpers.","commonSituations":"Enabling knownHelpersOnly for performance/strictness and later adding template features with new helpers; built-in helpers like #each/#if also need listing unless using block params defaults.","solutions":["Add the missing helper to options.knownHelpers (e.g. knownHelpers: {bar: true}).","Remove knownHelpersOnly to allow runtime helper resolution.","Register the helper and include it in the knownHelpers map used by both runtime and compiler."],"exampleFix":"// before\nHandlebars.compile(tpl, {knownHelpersOnly: true, knownHelpers: {upper: true}});\n// after\nHandlebars.compile(tpl, {knownHelpersOnly: true, knownHelpers: {upper: true, lower: true}});","handlingStrategy":"validation","validationCode":"function compileStrict(src, helpers) {\n  const used = collectHelperNames(Handlebars.parse(src)); // walk MustacheStatement/SubExpression\n  const missing = used.filter(h => !(h in helpers));\n  if (missing.length) throw new Error('Helpers not in knownHelpers: ' + missing.join(', '));\n  return Handlebars.compile(src, { knownHelpersOnly: true, knownHelpers: fromEntries(Object.keys(helpers).map(h => [h, true])) });\n}","typeGuard":null,"tryCatchPattern":"try { return compileFn(data); } catch (e) { if (/knownHelpersOnly/.test(e.message)) { /* add helper to knownHelpers or disable strict mode */ } throw e; }","preventionTips":["Keep the knownHelpers map generated from the same registry used at runtime.","Extract helper names from templates and diff against knownHelpers in CI.","Avoid knownHelpersOnly unless you control every template."],"tags":["compiler-options","knownhelpers","helpers"],"backgroundTag":"unknown-helper","analyzedSha":"13a7a679910d2adbfe7f6fad61ce8f98426b0378","analyzedAt":"2026-09-02T20:25:07.518Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}