← All guides

Why mermaid diagrams don't render in PDF (and how to fix it)

If your Markdown exports to PDF with the mermaid diagram showing up as raw code (the graph TD; A-->B text instead of an actual diagram), the reason is fundamental: mermaid is a JavaScript library that draws diagrams by running code in a browser. Any converter that does not execute JavaScript, which includes most static Markdown-to-PDF tools, pandoc without a special filter, and nbconvert, has no way to turn the mermaid code into a picture, so it leaves the code block as-is. To get a rendered diagram you need a converter that actually runs mermaid.js (a headless-browser or browser-based tool), or you pre-render the diagram to an image first. PDFMoka's markdown to PDF converter runs mermaid in the browser so diagrams render to the PDF; below is why this happens and every way to fix it.

The root cause: mermaid needs JavaScript to exist as a picture

A mermaid diagram in Markdown is just a fenced code block tagged mermaid:

```mermaid
graph TD;
  A-->B;
  A-->C;
```

That text is not an image. It only becomes a diagram when mermaid.js parses it and draws SVG, and that requires a JavaScript runtime. This is why the same diagram renders on GitHub or in a live preview but comes out as plain code in an export: GitHub and the preview run JavaScript; the exporter often does not. As the mermaid community puts it, treat mermaid as a renderer feature, not as portable Markdown, whether it renders depends entirely on the destination running mermaid.

So the failure splits into two questions: does your converter run JavaScript at all, and if so, is mermaid actually being invoked?

Fix 1: use a converter that runs mermaid.js

Tools that drive a headless browser (or run in the browser) can execute mermaid and capture the resulting diagram.

  • Browser-based converter: PDFMoka's markdown to PDF tool renders mermaid in your browser and includes the drawn diagram in the PDF, with no upload and no local setup. (Implementation note: mermaid is loaded on demand only when a document actually contains a mermaid block, so documents without diagrams stay lightweight.)

    verify against your build: confirm the exact behavior of your own converter on a document with several mermaid blocks before publishing, specifically, whether every diagram type you care about (flowchart, sequence, gantt, state) renders, and what the tool does when a diagram fails to parse (see Fix 3). Describe the real, observed behavior here rather than assuming.

  • VS Code "Markdown PDF" and similar extensions: these use headless Chromium and can render mermaid, but a well-known gotcha is that mermaid stays as raw code unless the extension's Chromium path (executablePath) is configured. If your extension exports code instead of diagrams, check that setting.

  • Pandoc: does not render mermaid on its own. You need a filter such as mermaid-filter (which itself calls mermaid-cli), plus its dependencies. Without the filter, pandoc passes the code block through unrendered.

Fix 2: pre-render the diagram to an image (works everywhere)

If you must use a converter that cannot run mermaid (a pure static/LaTeX pipeline), convert the diagram to a static image before the Markdown export, then reference that image instead of the code block. The mermaid CLI does this:

npm install -g @mermaid-js/mermaid-cli
mmdc -i diagram.mmd -o diagram.svg   # or .png

Then in your Markdown, replace the ```mermaid fenced block with ![diagram](diagram.svg). Now any converter, even one that ignores JavaScript, embeds the image like any other picture. This is the most portable fix: it removes the JavaScript dependency from export time entirely.

verify against current docs: the mermaid-cli package name and mmdc flags are current, but confirm before relying on them; mermaid-cli itself uses a headless browser under the hood, so it has its own Chromium requirement.

Fix 3: when the diagram is valid but still fails

Sometimes the converter does run mermaid but the diagram still breaks (a bomb icon, a blank space, or a getBoundingClientRect error). Common causes:

  • A mermaid syntax error. One malformed line fails the whole diagram. Test the diagram in the mermaid live editor to isolate syntax problems from converter problems.
  • A mermaid version mismatch. Some export tools pin an old mermaid version that chokes on newer syntax (or vice versa). If a diagram works in one tool and not another, version skew is a prime suspect.
  • Timing/layout issues in headless rendering, the diagram is captured before mermaid finishes drawing. This is a tool bug, not your diagram; a mature converter waits for render completion.

A good converter should tell you when a diagram could not be rendered rather than silently dropping it. If you rely on diagrams in important documents, prefer a tool that surfaces a clear warning on failure.

Which fix?

  • Want diagrams to just render, no pre-processing: use a converter that runs mermaid.js, like PDFMoka's markdown to PDF.
  • Stuck with a static/LaTeX pipeline: Fix 2, pre-render to SVG/PNG with mermaid-cli and embed the image.
  • Diagram renders elsewhere but fails on export: check syntax in the live editor and suspect a mermaid version mismatch.

For the related math-rendering version of this same "needs special handling" problem, see rendering LaTeX math in Markdown PDF exports.

References