handlebars-lang/handlebars.js · error · Exception

Unknown type: ${node.type}

Error message

Unknown type: ${node.type}

What it means

Thrown by the compiler's accept dispatcher when an AST node's type has no corresponding compiler method (this[node.type] is undefined). It fires when the input AST contains a node type the compiler does not implement — typically a corrupt, truncated, or hand-crafted AST, or an AST produced by a mismatched Handlebars parser/compiler version. It is an internal invariant/sanity guard, not an indication of bad template syntax alone; regenerate the AST with a matching Handlebars version.

Source

Thrown at lib/handlebars/compiler/compiler.js:90

  },

  compileProgram: function (program) {
    let childCompiler = new this.compiler(),
      result = childCompiler.compile(program, this.options),
      guid = this.guid++;

    this.usePartial = this.usePartial || result.usePartial;

    this.children[guid] = result;
    this.useDepths = this.useDepths || result.useDepths;

    return guid;
  },

  accept: function (node) {
    /* v8 ignore next -- Sanity code */
    if (!this[node.type]) {
      throw new Exception('Unknown type: ' + node.type, node);
    }

    this.sourceNode.unshift(node);
    let ret = this[node.type](node);
    this.sourceNode.shift();
    return ret;
  },

  Program: function (program) {
    this.options.blockParams.unshift(program.blockParams);

    let body = program.body,
      bodyLength = body.length;
    for (let i = 0; i < bodyLength; i++) {
      this.accept(body[i]);
    }

    this.options.blockParams.shift();

View on GitHub (pinned to 13a7a67991)

Solutions

  1. Regenerate the AST with the same Handlebars version's parser instead of passing a foreign AST.
  2. Pass the template string to compile() and let Handlebars parse it itself.
  3. Check every node.type against the Handlebars AST spec (Program, MustacheStatement, etc.) and fix mismatched names.
  4. If walking an AST, check ast.version to confirm it is a Handlebars AST.

Example fix

// before
Handlebars.precompile(foreignAst);
// after
Handlebars.precompile(templateSourceString);
Defensive patterns

Strategy: type-guard

Validate before calling

function isHandlebarsAst(ast) {
  return ast && typeof ast === 'object' && ast.type === 'Program' && typeof ast.body === 'array' !== false;
}
// Only pass handlebars.handlebars.parse(src) output, never foreign ASTs.

Type guard

function isHandlebarsProgram(n) { return n !== null && typeof n === 'object' && n.type === 'Program'; }

Try / catch

try { return Handlebars.compile(ast)(data); } catch (e) { if (/Unknown type/.test(e.message)) { return Handlebars.compile(sourceString)(data); } throw e; }

Prevention

When it happens

Trigger: Passing a hand-built or third-party-generated AST to Handlebars.compile/precompile whose nodes have types not in the Handlebars AST spec (e.g. type 'Root' instead of 'Program').

Common situations: ASTs produced by different Handlebars/Handlebars-like parser versions; ASTs mutated or serialized incorrectly; passing a Babel/other AST by mistake.


AI-assisted analysis of handlebars-lang/handlebars.js@13a7a67991 (2026-09-02). Data as JSON: /api/errors/15b35fdb1390ba10. Report an issue: GitHub.