mermaid-js/mermaid · error · MermaidParseError

Parsing failed: ${lexerErrors} ${parserErrors}

Error message

Parsing failed: ${lexerErrors} ${parserErrors}

What it means

The ABNF railroad parser runs the input through a Langium parser; if either the lexer or the parser reports any errors it wraps the ParseResult in a MermaidParseError whose message lists every lexer and parser error with line/column. The diagram is rejected before its rules are added to the db, so no partial railroad is rendered.

Source

Thrown at packages/mermaid/src/diagrams/railroad/parser/abnfParser.ts:137

const populateDb = (ast: RailroadAbnf): void => {
  populateCommonDb(ast, db);

  if (ast.title) {
    db.setTitle(ast.title);
  }

  ast.rules.map((rule) => db.addRule(transformRule(rule)));
};

export const parser: ParserDefinition = {
  parse: (input: string): void => {
    db.clear();
    log.debug('[ABNF Parser] Starting Langium parse');

    const result = langiumParser.parse<RailroadAbnf>(input);
    if (result.lexerErrors.length > 0 || result.parserErrors.length > 0) {
      throw new MermaidParseError(result);
    }

    const ast = result.value;
    log.debug('[ABNF Parser] Parsed rules:', ast.rules.length);

    populateDb(ast);
    log.debug('[ABNF Parser] Parse complete');
  },
  parser: {
    yy: db,
  },
};

export default parser;

View on GitHub (pinned to d93e9c88c0)

Solutions

  1. Read the embedded line/column in the message and fix the first reported error (later errors often cascade).
  2. Confirm the diagram type matches the grammar: use the ABNF flavor only for ABNF-style input.
  3. Validate the grammar in an external ABNF checker, then re-render.
  4. If integrating programmatically, catch MermaidParseError and surface e.result.lexerErrors / e.result.parserErrors to the user.

Example fix

// before — '=' is not ABNF rule syntax
rule = "a" | "b"

// after — ABNF uses '=' as definition operator with CRLF
rule = %x61 / %x62
Defensive patterns

Strategy: try-catch

Validate before calling

// No safe pre-check for grammar validity without parsing; lint heuristics only
if (!/::=|=/.test(input) && !input.trim()) {
  throw new Error('Empty railroad ABNF input');
}

Type guard

import { MermaidParseError } from '@mermaid-js/parser';
const isMermaidParseError = (e): e is MermaidParseError =>
  e instanceof MermaidParseError || (e instanceof Error && /^Parsing failed:/.test(e.message));

Try / catch

try {
  parser.parse(input);
} catch (e) {
  if (e instanceof MermaidParseError) {
    const lex = e.result.lexerErrors.map(er => `${er.line}:${er.column} ${er.message}`);
    const par = e.result.parserErrors.map(er => `${er.token.startLine}:${er.token.startColumn} ${er.message}`);
    showDiagnostics([...lex, ...par]);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling parser.parse(input) (the ABNF ParserDefinition) with text that violates the railroad ABNF grammar — unterminated rule, illegal character, unknown production, or malformed syntax. Equivalent guards exist for the EBNF, PEG and generic railroad grammars.

Common situations: Picking the wrong grammar flavor for the input (e.g. EBNF `::=` syntax fed to the ABNF parser), pasting grammar from another tool with different meta-syntax, stray unicode/whitespace, or a partial copy that cut a rule in half.

Related errors


AI-assisted analysis of mermaid-js/mermaid@d93e9c88c0 (2026-08-12). Data as JSON: /api/errors/08ec5e63ebe0c334. Report an issue: GitHub.