How Mermaid Handles Parsing Errors: ParseErrorFunction and DetailedError Types Explained

Mermaid provides a ParseErrorFunction hook and DetailedError interface that allow developers to intercept syntax errors during diagram rendering, receiving structured error objects containing line numbers, column positions, and original error contexts.

When rendering diagrams with the mermaid-js/mermaid library, syntax errors in diagram definitions can disrupt the rendering pipeline or produce opaque failure messages. The library exposes a flexible error handling mechanism through the ParseErrorFunction type and DetailedError interface, enabling applications to capture parsing diagnostics and provide user-friendly feedback. This system normalizes errors from the underlying Langium parser into a consistent format that custom handlers can process according to application needs.

How Mermaid Processes Parsing Errors Internally

Mermaid separates syntax parsing from runtime rendering through a six-stage pipeline that transforms low-level parser exceptions into structured error objects.

Stage 1: Parser Exception Generation

Each diagram type is parsed by a Langium-based parser. When lexical or grammatical errors are detected, the parser throws a MermaidParseError (which extends the native JavaScript Error class) with a concatenated message containing line- and column-specific details. This occurs in packages/parser/src/parse.ts at lines 73-97.

Stage 2: API-Level Error Capture

The mermaidAPI.parse method propagates the thrown error back to the higher-level wrapper (mermaid.parse). The performCall helper in packages/mermaid/src/mermaid.ts (lines 62-66) manages this propagation, ensuring errors bubble up from the diagram-specific parser to the public API surface.

Stage 3: Error Normalization via handleError

The handleError helper receives the raw error (typed as unknown). If the object matches the DetailedError shape (containing str, hash, and other expected properties), it is pushed into an internal errors array. Otherwise, the error is wrapped into a DetailedError-like object containing a string message and optional name. This normalization occurs in packages/mermaid/src/mermaid.ts at lines 64-78, ensuring the public parseError callback receives a consistent data structure regardless of the error source.

Stage 4: parseError Hook Invocation

The global mermaid.parseError callback (type ParseErrorFunction) is invoked with either (msg, hash?) when a DetailedError is available, or with a single string argument when only a plain message is present. This hook can be set directly via property assignment (mermaid.parseError = fn) or through the setParseErrorHandler helper method. The callback type is defined in packages/mermaid/src/Diagram.ts at lines 9-11, while invocation occurs in the same file as the normalization step.

Stage 5: DetailedError Object Structure

The DetailedError interface supplies a standardized error payload containing:

  • str — the human-readable message
  • hash — optional context metadata (e.g., line/column positions)
  • error? — the original Error object for stack trace access
  • message? — duplicate of str for convenience

This interface is defined in packages/mermaid/src/utils.ts at lines 83-90, and includes the isDetailedError runtime type guard to validate error shapes.

Stage 6: Error Bubbling Behavior

If options.suppressErrors is false (the default), the first DetailedError collected during a run call is re-thrown after all diagrams have been processed. This allows callers to catch parsing failures using standard try/catch blocks. The re-throwing logic resides in runThrowsErrors within packages/mermaid/src/mermaid.ts at lines 96-100.

ParseErrorFunction and DetailedError Type Definitions

Understanding the type signatures is essential for implementing custom error handlers that integrate cleanly with TypeScript codebases.

ParseErrorFunction Interface

Defined in packages/mermaid/src/Diagram.ts, this type describes the callback signature:

export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void;

The err parameter accepts either a plain string, a full DetailedError object, or any unknown payload. The optional hash parameter provides secondary context historically used for line numbers and positional data.

DetailedError Interface

Defined in packages/mermaid/src/utils.ts, this interface structures the normalized error:

export interface DetailedError {
  str: string;          // readable error description
  hash: any;            // optional user-provided data (e.g., line/col)
  error?: any;          // original Error instance (if any)
  message?: string;     // duplicate of `str` for convenience
}

The companion type guard function validates runtime objects:

export function isDetailedError(error: any): error is DetailedError {
  return 'str' in error;
}

This guard is exported from packages/mermaid/src/utils.ts and allows handlers to narrow union types safely.

Implementing Custom Error Handlers in Mermaid

Developers can hook into the error pipeline at multiple integration points depending on their environment constraints.

Registering a Global Error Handler

For environments where the global object might be frozen or when explicit API usage is preferred, use the setParseErrorHandler helper:

// Register via the explicit helper
mermaid.setParseErrorHandler((msg, hash) => {
  console.warn('Mermaid parse error:', msg);
  if (hash) {
    console.warn('Additional context:', hash);
  }
});

Source: setParseErrorHandler implementation in packages/mermaid/src/mermaid.ts (lines 90-106).

Direct Assignment to parseError

In browser environments with standard global access, direct property assignment provides a simpler integration path:

mermaid.parseError = (detail) => {
  if (typeof detail === 'string') {
    alert('Syntax error: ' + detail);
  } else {
    // `detail` is a DetailedError object
    alert(`Error: ${detail.str}\nAt: ${detail.hash}`);
  }
};

Source: Property defined on the Mermaid interface in packages/mermaid/src/mermaid.ts (lines 34-36).

Handling Errors with suppressErrors

When programmatically parsing diagram definitions, control error throwing behavior through the suppressErrors option:

try {
  const result = await mermaid.parse('flowchart X\n a-->b', { suppressErrors: false });
  console.log('Parsed OK:', result);
} catch (e) {
  // e is a DetailedError (or array of them) if a custom handler is not set
  console.error('Parse failed:', e);
}

Source: parse wrapper implementation in packages/mermaid/src/mermaid.ts (lines 47-66).

Inspecting DetailedError Properties

Handlers should validate the error structure before accessing specific properties:

mermaid.setParseErrorHandler((err) => {
  if (typeof err === 'object' && err.str) {
    console.log('Message:', err.str);
    console.log('Original error:', err.error);
    console.log('Context data:', err.hash);
  } else {
    console.log('String error:', err);
  }
});

Source: DetailedError interface definition in packages/mermaid/src/utils.ts (lines 83-90).

Key Source Files for Error Handling

The error handling pipeline spans several modules across the mermaid monorepo:

  • packages/mermaid/src/mermaid.ts — Central orchestration including error capture via handleError, public parse/render wrappers, setParseErrorHandler, and the global parseError property assignment.

  • packages/mermaid/src/Diagram.ts — Declares the ParseErrorFunction type that consumers implement to receive error notifications.

  • packages/mermaid/src/utils.ts — Defines the DetailedError interface, the runtime type guard isDetailedError, and the getErrorMessage helper utility.

  • packages/parser/src/parse.ts — Implements the low-level Langium parser that throws MermaidParseError instances with rich line/column diagnostics.

Summary

  • Mermaid normalizes all parsing errors into DetailedError objects containing str (message), hash (context), and error (original exception) properties.
  • The ParseErrorFunction type defines the callback signature for custom error handlers, accepting either strings or DetailedError objects.
  • Register handlers via mermaid.setParseErrorHandler() for robust environments or direct mermaid.parseError assignment for simple browser integration.
  • Control error throwing with the suppressErrors option in mermaid.parse() to handle errors programmatically rather than via global callbacks.
  • Source files in packages/mermaid/src/mermaid.ts and packages/mermaid/src/utils.ts contain the core error transformation logic and type definitions.

Frequently Asked Questions

What is the difference between ParseErrorFunction and DetailedError?

ParseErrorFunction is a type alias describing the callback signature (err, hash?) => void that developers implement to receive error notifications. DetailedError is an interface defining the structured error object shape containing str, hash, error, and message properties. The function receives the error data; the interface describes the data format.

How do I access line and column numbers from a parsing error?

Access positional data through the hash property of the DetailedError object. When the Langium parser throws a MermaidParseError, the normalization process in handleError preserves line and column information within the hash field. Inspect err.hash inside your ParseErrorFunction implementation to extract specific location data.

Can I suppress errors globally while still logging them?

Yes. Set suppressErrors: true in the parse options to prevent errors from throwing, while simultaneously registering a parseError handler to log or process errors. Alternatively, set a global handler and catch the re-thrown error at the application level using try/catch blocks around mermaid.run() or mermaid.parse() calls.

What happens if I don't set a custom parseError handler?

Without a custom handler, errors follow the default pipeline: they are normalized to DetailedError objects, collected in an internal array, and if suppressErrors is false, the first error is re-thrown after processing completes. This results in standard JavaScript exceptions that can be caught with try/catch, though without custom UI feedback or logging during the rendering process.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →