[Troubleshooting] Mermaid Diagram Syntax Errors in Markdown PDF Export
Resolving mysterious Mermaid syntax errors caused by HTML tag interpretation in angle brackets.
Introduction
While documenting API test scenarios with Mermaid flowcharts, I encountered a frustrating issue. Some diagrams rendered perfectly, while others showed the dreaded error:
1
2
Syntax error in text
mermaid version 11.12.2
The bizarre part? The diagrams looked identical in structure. This post documents the root causes and solutions for several hidden pitfalls in Mermaid diagram syntax.
Problem 1: AND and OR Breaking Edge Labels
Symptom
I was creating search API diagrams with conditional queries:
1
2
3
4
5
flowchart LR
Tester([Tester])
API[Search API]
Tester -->|"q=[cond1, AND, cond2]"| API
This resulted in a syntax error, while similar diagrams using IS, IN, NOT worked fine:
1
2
3
4
5
flowchart LR
Tester([Tester])
API[Search API]
Tester -->|"q=[col, IS, val]"| API
Root Cause
This isn’t a documented Mermaid feature, so treat the following as an empirical observation rather than a rule. In practice, AND and OR sitting bare inside an edge label seem to trigger a parsing conflict — likely an interaction with the surrounding brackets and commas in the label text — and even wrapping the label in quotes ("...") doesn’t always avoid it.
Note: the only officially reserved keyword in Mermaid flowcharts is the lowercase
end.ANDandORare not documented reserved operators; this is just a workaround for the parsing conflict above.
Solution
Add underscores around the offending words so they no longer trip the parser:
1
2
3
4
5
6
7
<!-- Before (Error) -->
q=[cond1, AND, cond2]
q=[cond1, OR, cond2]
<!-- After (Works) -->
q=[cond1, _AND_, cond2]
q=[cond1, _OR_, cond2]
Alternatively, you can use symbols like + and /:
1
2
q=cond1 + cond2 <!-- AND -->
q=cond1 / cond2 <!-- OR -->
The most portable fix, though, is to rephrase the whole edge label so the operator words never appear (e.g. q: cond1 + cond2 or q: all conditions).
Lesson: Bare AND/OR inside an edge label can trip Mermaid’s parser — rephrase the label or wrap the words (_AND_, or symbols +//) so the operator words never appear raw.
Problem 2: Angle Brackets Interpreted as HTML Tags
Symptom
Some response messages with angle brackets failed:
1
2
3
4
5
6
flowchart LR
A[API]
T([Tester])
A -.->|"200(rows=<row>)"| T
A -.->|"200(rows=<unchanged>)"| T
But these worked:
1
2
3
4
5
6
flowchart LR
A[API]
T([Tester])
A -.->|"200(rows=<1개>)"| T
A -.->|"200(rows=<원래값>)"| T
Root Cause Analysis
| Pattern | Result | Reason |
|---|---|---|
<row> | Error | Looks like HTML <row> tag |
<unchanged> | Error | Looks like HTML <unchanged> tag |
<1개> | Works | Contains number, not a valid tag |
<원래값> | Works | Contains Korean, not a valid tag |
The Markdown PDF exporter (or underlying HTML renderer) interprets English-only content in angle brackets as potential HTML tags, breaking the Mermaid parser.
Solution
The recommended general fix is to stop the renderer from seeing the angle brackets as a tag in the first place. There are three robust approaches, in order of preference:
Escape the brackets as HTML entities — replace
<with<and>with>so they render as literal characters (this is the approach the Mermaid flowchart docs recommend for special characters in labels):1 2 3 4 5 6 7
<!-- Before (Error) --> rows=<row> rows=<unchanged> <!-- After (Works) --> rows=<row> rows=<unchanged>
Wrap/quote the label text so the brackets stay inside a quoted string, e.g.
|"200(rows=<row>)"|, keeping the quotes already used in these edge labels.Remove the angle brackets entirely if they are purely decorative, e.g.
rows=roworrows=[row].
As a secondary quick hack, you can also break the HTML tag pattern by adding a non-English character (Korean, a number, or a symbol) so the content no longer looks like a valid tag:
1
2
3
<!-- Quick hack -->
rows=<해당row>
rows=<변경없음>
This works because the renderer only treats English-only content between < and > as a potential tag, but escaping is the more portable fix.
Lesson: An HTML-based renderer reads <english> in a label as a tag — escape the brackets as </> (the portable fix); adding a Korean character or number is only a quick hack.
Problem 3: The Infamous <meta> Tag
Symptom
This diagram consistently failed in my Markdown-PDF (Puppeteer/HTML) export pipeline, even with Korean characters nearby:
1
2
3
4
5
flowchart LR
ML[Meta Listing API]
T([Tester])
ML -.->|"200(rows=<meta값유지>)"| T
Root Cause
<meta> is a valid HTML tag!
1
<meta charset="UTF-8">
Even though <meta값유지> contains Korean, the parser sees <meta and interprets it as the start of an HTML meta tag, causing a parsing failure.
Solution
Because <meta> is a real tag, the Korean-character trick alone won’t save you here — <meta값유지> still starts with <meta. Escape the brackets instead:
1
2
3
4
5
<!-- Before (Error) -->
rows=<meta값유지>
<!-- After (Works) -->
rows=<meta값유지>
As a secondary quick hack, you can rename the token so the literal string meta no longer appears right after <, for example using its Korean equivalent:
1
2
<!-- Quick hack -->
rows=<메타값유지>
Lesson: For a real HTML tag name (<meta>, <div>, <span>), the non-English trick fails — the parser keys on the leading tag name, so always escape (<meta>).
Summary: Mermaid + HTML Parsing Gotchas
| Issue | Trigger | Solution |
|---|---|---|
| Edge-label parsing conflict | AND, OR in message labels | Use +, / or _AND_, _OR_ |
| HTML Tag Interpretation | <english> patterns | Escape as <row>, quote the label, or drop the brackets (quick hack: add Korean/numbers, <한글english>) |
| Actual HTML Tags | <meta>, <div>, <span>, etc. | Escape as <meta> (quick hack: rename, e.g. <메타>) |
Conclusion
Mermaid is powerful for documentation, but its integration with HTML-based renderers (like VS Code’s Markdown PDF extension) introduces hidden parsing conflicts.
Key Takeaways:
- Avoid bare
AND/ORinside message labels (the only officially reserved flowchart keyword isend). - For angle brackets in labels, escape them as HTML entities (
<row>), keep the label quoted, or remove the brackets — this is the portable fix recommended by the Mermaid flowchart docs. - Be especially careful with real HTML tag names like
<meta>,<div>,<span>; escaping handles these too.
When in doubt, escape the brackets. As a quick hack you can add a Korean character or number to break the pattern, but </> is the more reliable fix.