handlebars-lang/handlebars.js · error · Exception

replaceStack on non-inline

Error message

replaceStack on non-inline

What it means

replaceStack is an internal JavaScriptCompiler helper only valid while compiling an inline expression (isInline()). Calling it outside inline context would corrupt the emitted expression, so it throws.

Source

Thrown at lib/handlebars/compiler/javascript-compiler.js:935

        )
      );
      this.pendingContent = undefined;
    }

    if (source) {
      this.source.push(source);
    }
  },

  replaceStack: function (callback) {
    let prefix = ['('],
      stack,
      createdStack,
      usedLiteral;

    /* v8 ignore next */
    if (!this.isInline()) {
      throw new Exception('replaceStack on non-inline');
    }

    // We want to merge the inline statement into the replacement statement via ','
    let top = this.popStack(true);

    if (top instanceof Literal) {
      // Literals do not need to be inlined
      stack = [top.value];
      prefix = ['(', stack];
      usedLiteral = true;
    } else {
      // Get or create the current stack name for use by the inline
      createdStack = true;
      let name = this.incrStack();

      prefix = ['((', this.push(name), ' = ', top, ')'];
      stack = this.topStack();
    }

View on GitHub (pinned to 13a7a67991)

Solutions

  1. Only call replaceStack inside inline-emission contexts (guard with this.isInline()).
  2. Use popStack/pushStack directly instead of replaceStack in non-inline code paths.
  3. Upgrade Handlebars if the error arises from unpatched library code and file a bug with a repro.

Example fix

// before
const ref = this.replaceStack(...); // anywhere in custom opcode
// after
if (this.isInline()) { const ref = this.replaceStack(...); } else { const ref = this.popStack(); }
Defensive patterns

Strategy: try-catch

Try / catch

try { return compileWithCustomCompiler(src); } catch (e) { if (/replaceStack on non-inline/.test(e.message)) { fallBackToStockCompiler(); } throw e; }

Prevention

When it happens

Trigger: Custom JavaScriptCompiler subclass or monkey-patch invoking this.replaceStack when the current opcode emission is not inline; misuse in compiler extensions.

Common situations: Authors of Handlebars compiler plugins/forks extending codegen; internal invariant violation in patched builds.

Related errors


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