{"record":{"id":"5e26963db5f00d1b","repo":"handlebars-lang/handlebars.js","slug":"unknown-template-object-typeof-templatespec","errorCode":null,"errorMessage":"Unknown template object: ${typeof templateSpec}","messagePattern":"Unknown template object: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"lib/handlebars/runtime.js","lineNumber":55,"sourceCode":"    );\n  } else {\n    // Use the embedded version info since the runtime doesn't know about this revision yet\n    throw new Exception(\n      'Template was precompiled with a newer version of Handlebars than the current runtime. ' +\n        'Please update your runtime to a newer version (' +\n        compilerInfo[1] +\n        ').'\n    );\n  }\n}\n\nexport function template(templateSpec, env) {\n  /* v8 ignore next */\n  if (!env) {\n    throw new Exception('No environment passed to template');\n  }\n  if (!templateSpec || !templateSpec.main) {\n    throw new Exception('Unknown template object: ' + typeof templateSpec);\n  }\n\n  templateSpec.main.decorator = templateSpec.main_d;\n\n  // Note: Using env.VM references rather than local var references throughout this section to allow\n  // for external users to override these as pseudo-supported APIs.\n  env.VM.checkRevision(templateSpec.compiler);\n\n  // backwards compatibility for precompiled templates with compiler-version 7 (<4.3.0)\n  const templateWasPrecompiledWithCompilerV7 =\n    templateSpec.compiler && templateSpec.compiler[0] === 7;\n\n  function invokePartialWrapper(partial, context, options) {\n    if (options.hash) {\n      context = Utils.extend({}, context, options.hash);\n    }\n    partial = env.VM.resolvePartial.call(this, partial, context, options);\n","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/handlebars-lang/handlebars.js/blob/13a7a679910d2adbfe7f6fad61ce8f98426b0378/lib/handlebars/runtime.js#L37-L73","documentation":"After checking the environment, `template()` validates that `templateSpec` is a real compiled template object by verifying `templateSpec.main` exists (the compiled template's entry function). If `templateSpec` is falsy or lacks `main`, it throws this Exception including the JavaScript typeof of the offending value, since whatever was passed is not a precompiled template.","triggerScenarios":"`template()` is called with null/undefined, with a plain object without a `main` property, with a spec from a mismatched/older compiler that lacks `main`, or with a raw template source string instead of a compiled spec object.","commonSituations":"Passing raw template source text to `Handlebars.template()` instead of `Handlebars.compile()`; importing the wrong file or an ESM/CJS interop default yielding `{}` or undefined; async import or bundler misconfiguration resolving to undefined; corrupted or truncated precompiled output.","solutions":["Pass the compiled spec produced by `Handlebars.precompile`/the precompiler output, not raw template text — use `Handlebars.compile(source)` if you only have source","Inspect `typeof templateSpec` (given in the message) and check for import/default-interop problems, e.g. use `mod.default` when importing precompiled ESM files","Re-run the precompiler to regenerate a complete template spec containing `main`","Fix the bundler/import path so the precompiled module resolves to the template object"],"exampleFix":"// before: passing raw source to template()\nconst tmpl = Handlebars.template('{{hello}}');\n\n// after: compile source, or pass precompiled spec\nconst tmpl = Handlebars.compile('{{hello}}');\n// or: const tmpl = Handlebars.template(precompiledSpec);","handlingStrategy":"type-guard","validationCode":"import Handlebars from 'handlebars/runtime';\n\nfunction assertTemplateSpec(spec) {\n  if (!spec || typeof spec.main !== 'function') {\n    throw new Error(`Expected compiled template spec with main(), got ${typeof spec}`);\n  }\n}\nassertTemplateSpec(spec);\nconst tmpl = Handlebars.template(spec);","typeGuard":"function isTemplateSpec(v) {\n  return v != null && typeof v === 'object' && typeof v.main === 'function';\n}","tryCatchPattern":"try {\n  const tmpl = Handlebars.template(templateSpec);\n} catch (e) {\n  if (e.message.startsWith('Unknown template object')) {\n    throw new Error(`Bad template import for ${tplPath}: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Never pass raw template strings to Handlebars.template — use Handlebars.compile for source","Check ESM/CJS interop: use mod.default when a precompiled module wraps the spec","Validate the precompiled output file is non-empty and contains a main entry after building","Keep precompiler and runtime versions matched so the spec shape always includes main"],"tags":["handlebars","precompiled-template","invalid-argument","template-spec"],"backgroundTag":"invalid-template-object","analyzedSha":"13a7a679910d2adbfe7f6fad61ce8f98426b0378","analyzedAt":"2026-09-02T20:25:07.518Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}