All posts
MermaidTroubleshootingCommon ErrorsBest PracticesDeveloper Tips

Common Mermaid diagram errors and how to fix them fast

6 min readThe MermaidCreator team

You've drafted a flowchart, hit save, and the diagram vanishes. Or you've nested a sequence diagram's alt blocks and the syntax refuses to parse. These moments derail diagramming sessions—especially when you're in a meeting and just need the diagram to work. This guide covers the 10 most common Mermaid mistakes and exact fixes.

1. Invalid syntax in node labels with special characters

The problem: Node labels with brackets, pipes, or dashes break the parser.

flowchart LR
    A[To do: buy milk & eggs]
    B[Output: foo | bar]
    A --> B

This fails because & and | are reserved.

The fix: Escape or quote:

flowchart LR
    A["To do: buy milk & eggs"]
    B["Output: foo | bar"]
    A --> B

Wrap labels in double quotes and use HTML entities (&, <, >) or plain text without reserved symbols.

2. Indentation errors in sequence diagrams

The problem: Your sequenceDiagram works, but alt / else blocks are indented wrong.

sequenceDiagram
    participant A
    participant B
    A->>B: Hi
    alt Success
    B-->>A: OK
    else Error
    B-->>A: Failed
    end

This breaks because Mermaid expects the alt content to be indented (or at the same level, depending on the version).

The fix: Keep content at the same indentation level as the block keyword:

sequenceDiagram
    participant A
    participant B
    A->>B: Hi
    alt Success
        B-->>A: OK
    else Error
        B-->>A: Failed
    end

Or omit indentation entirely—Mermaid is flexible, but consistency avoids surprises.

3. Forgetting the end keyword

The problem: You nested alt blocks or loops but forgot to close one.

sequenceDiagram
    A->>B: Request
    alt Valid
        B-->>A: 200 OK
    else Invalid
        B-->>A: 400 Bad Request
    loop Retry
        A->>B: Again
        B-->>A: 200 OK

Missing end for the loop block stops parsing.

The fix: Count your block openers and closers. Every alt, loop, par, rect, etc., needs an end:

sequenceDiagram
    A->>B: Request
    alt Valid
        B-->>A: 200 OK
    else Invalid
        B-->>A: 400 Bad Request
    end
    loop Retry
        A->>B: Again
        B-->>A: 200 OK
    end

Pro tip: In MermaidCreator's code editor, use bracket-matching to spot unclosed blocks.

4. Wrong arrow syntax in flowcharts

The problem: Flowchart arrows have specific meanings, and the wrong one breaks readability (or syntax):

flowchart LR
    A ==> B
    B -. C
    C -- D

==> isn't valid; -. is incomplete; -- is only for open lines, not connections.

The fix: Use the correct syntax:

ArrowSyntaxMeaning
Solid-->Normal flow
Bold==>Not valid; use -->
Dashed-.->Alternate flow / optional
Dotted-..->Weak dependency
Openo--oCircle endpoints

Correct example:

flowchart LR
    A --> B
    B -.-> C
    C -..-> D

5. Circular dependencies breaking layout

The problem: Your graph has cycles (A → B → A), and Mermaid's layout engine struggles to position nodes without overlap.

flowchart LR
    A --> B
    B --> C
    C --> A

This renders, but nodes overlap or scatter unpredictably depending on the viewing context.

The fix: Cycles are real—don't hide them, but visualize them clearly. Use explicit node positioning hints (LR, TB, RL, BT):

flowchart TB
    A --> B
    B --> C
    C --> A
    D --> A
    style A fill:#f9f,stroke:#333

Or break the cycle visually with labels:

flowchart LR
    A["Action A"]
    B["Action B"]
    C["Action C (loops back)"]
    A --> B
    B --> C
    C -->|feedback| A

6. Mismatched subgraph syntax

The problem: Subgraphs (clusters in flowcharts) don't close properly:

flowchart LR
    subgraph A [Frontend]
        B["React App"]
    subgraph B [Backend]
        C["API"]

Missing end keywords and unclear scope.

The fix: Each subgraph needs subgraph ID [Label] ... end:

flowchart LR
    subgraph A ["Frontend"]
        B["React App"]
    end
    subgraph B ["Backend"]
        C["API"]
    end
    B --> C

Use unique IDs (A, B) and clear labels in brackets. Always close with end.

7. Participant aliasing gone wrong in sequences

The problem: You declared participant X as Really Long Name but then referenced X inconsistently:

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: Hello
    Server-->>C: Hi

The second message uses Server (the alias's label) instead of S (the alias ID).

The fix: Reference participants by their alias ID, not their label:

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: Hello
    S-->>C: Hi

Alias IDs are single letters or short identifiers; labels are the long names shown in the diagram.

8. State diagram syntax confusion

The problem: State diagrams expect arrow syntax different from flowcharts:

stateDiagram-v2
    [*] -> Idle
    Idle --> Processing
    Processing --> Done
    Done -> [*]

Using --> works, but the direction might surprise you.

The fix: State diagrams use similar arrow syntax to flowcharts, but the rendering is state-specific. Use --> for transitions and [*] for start/end:

stateDiagram-v2
    [*] --> Idle
    Idle --> Processing
    Processing --> Done
    Done --> [*]

Wrap state names with spaces in quotes: "Active Loading"

9. Class diagram visibility modifiers misplaced

The problem: Class diagrams use +, -, # for visibility, but placing them wrong breaks parsing:

classDiagram
    class User
        + name: string
        - password: string
        authenticate()

The format is unclear; Mermaid expects specific syntax.

The fix: Use the strict format for class definitions:

classDiagram
    class User {
        +name: string
        -password: string
        #internal_id: int
        +authenticate(): bool
    }
  • + = public
  • - = private
  • # = protected

10. ER diagram relationship syntax errors

The problem: ER diagrams use specific relationship symbols, and the syntax is easy to misremember:

erDiagram
    USER ||--o| ORDER
    ORDER ||--|| PRODUCT

The pipes and O's need to be in the exact right order.

The fix: ER relationships follow a specific pattern: |o, ||, }o, }{ for different cardinalities.

RelationshipSymbolMeaning
One to one||Both sides mandatory
One to many||--o|One side many, optional
Optionalo|Zero or one
Many}oOne or more (no SQL equivalent)

Correct example:

erDiagram
    USER ||--o{ ORDER : places
    ORDER ||--|| PRODUCT : contains
    PRODUCT o{--o{ CATEGORY : in

Quick debugging checklist

When a diagram fails to render:

  1. Check the browser console — Mermaid errors appear there first
  2. Verify all block openers have closersalt, loop, subgraph, etc. need end
  3. Quote labels with special characters["Label with & symbols"]
  4. Match arrow syntax to diagram type — flowchart arrows differ from state diagram arrows
  5. Count indentation carefully — especially in sequence diagrams
  6. Test incrementally — start with a minimal diagram and add complexity step by step

Use the MermaidCreator editor to draft and test diagrams with instant visual feedback—catch errors before they escape to production.

FAQ

Why does my diagram work locally but not in GitHub?
GitHub might be using an older Mermaid version. Test against the version you're using in your project by checking the package.json or the latest CDN version.

Can I use Unicode characters in node labels?
Yes, but wrap them in quotes: ["🚀 Launch"]. Some characters may render differently depending on the browser or font.

How do I debug a syntax error if the error message is vague?
Start with a single node, then add connections one by one. The moment it breaks, you've found the culprit. Mermaid's error reporting is improving, but incremental testing is still the fastest debugging technique.

Paste your broken diagram into the MermaidCreator editor for instant syntax checking and visual feedback—most errors become obvious in the live preview.

Related posts