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 messagehash— optional context metadata (e.g., line/column positions)error?— the originalErrorobject for stack trace accessmessage?— duplicate ofstrfor 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 viahandleError, publicparse/renderwrappers,setParseErrorHandler, and the globalparseErrorproperty assignment. -
packages/mermaid/src/Diagram.ts— Declares theParseErrorFunctiontype that consumers implement to receive error notifications. -
packages/mermaid/src/utils.ts— Defines theDetailedErrorinterface, the runtime type guardisDetailedError, and thegetErrorMessagehelper utility. -
packages/parser/src/parse.ts— Implements the low-level Langium parser that throwsMermaidParseErrorinstances with rich line/column diagnostics.
Summary
- Mermaid normalizes all parsing errors into
DetailedErrorobjects containingstr(message),hash(context), anderror(original exception) properties. - The
ParseErrorFunctiontype defines the callback signature for custom error handlers, accepting either strings orDetailedErrorobjects. - Register handlers via
mermaid.setParseErrorHandler()for robust environments or directmermaid.parseErrorassignment for simple browser integration. - Control error throwing with the
suppressErrorsoption inmermaid.parse()to handle errors programmatically rather than via global callbacks. - Source files in
packages/mermaid/src/mermaid.tsandpackages/mermaid/src/utils.tscontain 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →