{"record":{"id":"f1e83eb326b8f8fe","repo":"handlebars-lang/handlebars.js","slug":"you-must-pass-a-string-or-handlebars-ast-to-handle","errorCode":null,"errorMessage":"You must pass a string or Handlebars AST to Handlebars.compile. You passed ${input}","messagePattern":"You must pass a string or Handlebars AST to Handlebars\\.compile\\. You passed (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"lib/handlebars/compiler/compiler.js","lineNumber":481,"sourceCode":"      );\n    return env.template(templateSpec);\n  }\n\n  // Template is only compiled on first use and cached after that point.\n  return function (context, execOptions) {\n    if (!compiled) {\n      compiled = compileInput();\n    }\n    return compiled.call(this, context, execOptions);\n  };\n}\n\nfunction validateInput(input, options) {\n  if (\n    input == null ||\n    (typeof input !== 'string' && input.type !== 'Program')\n  ) {\n    throw new Exception(\n      'You must pass a string or Handlebars AST to Handlebars.compile. You passed ' +\n        input\n    );\n  }\n\n  if (options.trackIds || options.stringParams) {\n    throw new Exception(\n      'TrackIds and stringParams are no longer supported. See Github #1145'\n    );\n  }\n\n  if (!('data' in options)) {\n    options.data = true;\n  }\n  if (options.compat) {\n    options.useDepths = true;\n  }\n}","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/handlebars-lang/handlebars.js/blob/13a7a679910d2adbfe7f6fad61ce8f98426b0378/lib/handlebars/compiler/compiler.js#L463-L499","documentation":"Handlebars.compile/precompile validates its input: it must be a template string or a Handlebars AST whose root type is 'Program' (and not null/undefined). Anything else — objects, arrays, numbers, parsed HTML — is rejected with this message including the value.","triggerScenarios":"compile(undefined), compile(null), compile({template: '...'}), compile(someArray), or passing the wrong variable (e.g. an options object or a DOM node).","commonSituations":"Async template loading where the string hasn't arrived yet (undefined at compile time); passing a jQuery/cheerio object instead of its text; typos in variable names.","solutions":["Ensure the input is the template source string: compile('<h1>{{title}}</h1>').","If compiling an AST, pass the root node with type 'Program' produced by Handlebars.parse.","Await async template fetches before calling compile; check for undefined.","Log/inspect the value passed to compile to spot wrong-variable mistakes."],"exampleFix":"// before\nconst tpl = Handlebars.compile(await fetchTemplate()) /* returns object */;\n// after\nconst src = await fetchTemplate();\nconst tpl = Handlebars.compile(typeof src === 'string' ? src : src.template);","handlingStrategy":"type-guard","validationCode":"function safeCompile(input, options) {\n  if (input == null || (typeof input !== 'string' && input.type !== 'Program')) {\n    throw new TypeError('compile() needs a template string or Handlebars AST, got: ' + input);\n  }\n  return Handlebars.compile(input, options);\n}","typeGuard":"function isCompilableInput(v) { return typeof v === 'string' || (v !== null && typeof v === 'object' && v.type === 'Program'); }","tryCatchPattern":"try { const tpl = Handlebars.compile(input); } catch (e) { if (/string or Handlebars AST/.test(e.message)) { /* resolve async source or fix variable */ } throw e; }","preventionTips":["Await all async template sources before compiling.","Pass strings, not DOM/jQuery wrapper objects.","Centralize compile() calls behind a validating wrapper."],"tags":["compile","type-error","input-validation"],"backgroundTag":"invalid-compile-input","analyzedSha":"13a7a679910d2adbfe7f6fad61ce8f98426b0378","analyzedAt":"2026-09-02T20:25:07.518Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}