6

I’m using langgraph in a Jupyter notebook to build a simple state machine and then render the graph with Mermaid via mermaid.ink. In one snippet of code, naming the node "A" causes a timeout error from Mermaid:

%%capture --no-stderr
%pip install -U langgraph typing-extensions
from IPython.display import Image
from typing_extensions import TypedDict
from langgraph.graph import StateGraph

class ClientContext(TypedDict):
    client_id: str

graph_builder = StateGraph(ClientContext)

def chatbot(state: ClientContext):
    return {"messages": "Yam"}

graph_builder.add_node("A", chatbot)
graph_builder.set_entry_point("A")
graph_builder.set_finish_point("A")
graph = graph_builder.compile()

graph_image = Image(graph.get_graph().draw_mermaid_png())  # <-- Times out

The error is:

TimeoutError: The read operation timed out

requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='mermaid.ink', port=443): 
Read timed out. (read timeout=10)

Has anyone else encountered Mermaid timeout errors specifically tied to certain node labels in langgraph or Mermaid diagrams?

When I change the node name to "chatbot" (see code below), everything runs normally and the Mermaid diagram is successfully rendered:

from IPython.display import Image
from typing_extensions import TypedDict
from langgraph.graph import StateGraph

class ClientContext(TypedDict):
    client_id: str

graph_builder = StateGraph(ClientContext)

def chatbot(state: ClientContext):
    return {"messages": "Yam"}

graph_builder.add_node("chatbot", chatbot)
graph_builder.set_entry_point("chatbot")
graph_builder.set_finish_point("chatbot")
graph = graph_builder.compile()

graph_image = Image(graph.get_graph().draw_mermaid_png())  # <-- Works
1
  • 1
    this happen to me today, I just realized that custom name really does not work? these names works: "chatbot" "chat_bot" "bot" but when I changed to: "chatbot_x" "botchat" "bot1" "chatbot1", it does not work... Commented Apr 21 at 18:19

6 Answers 6

14

One solution that always works with langgraph:

graph.get_graph().print_ascii()

langgraph has native ASCII support

So until mermaid fixes the bug, I will fall back to this solution.

Sign up to request clarification or add additional context in comments.

3 Comments

In this case remember to pip install grandalf
Nice to have !!!
The above line of code works for me.
3

I have same issue. tried all the steps in the error code, but nothing helps.

Other users report similar issues (however 3 weeks ago) on mermaid.ink github repo. I opened a ticket here: https://github.com/jihchi/mermaid.ink/issues/521

I cross-reference this page here to document that i am not the only one with this issue.

i can confirm that using names, from preious (successfull) runs lead to correct images (so assumption cache most likely true) but after changing the names, same rendering error occurs. Here is my error text (only the last few lines): ValueError: Failed to reach https://mermaid.ink/ API while trying to render your graph after 1 retries. To resolve this issue:

  1. Check your internet connection and try again
  2. Try with higher retry settings: draw_mermaid_png(..., max_retries=5, retry_delay=2.0)
  3. Use the Pyppeteer rendering method which will render your graph locally in a browser: draw_mermaid_png(..., draw_method=MermaidDrawMethod.PYPPETEER)

I am running the command "jupyter notebook" and using the jupyter notebooks from the langchain academy (the langgraph course), so it should work.

I also searched internet, but it seems that this error is pretty new.

Comments

2

I'm having the same issue with the mermaid servers since a week ago (or so). I tried running the server locally on docker and it works as expected. For the issue with node names I'm assuming your Jupyter notebook is caching the image for a previously created graph and when you use that old name it just uses the cache hence you don't see an error. Try creating a new notebook (or even better a whole new python environment), and run both codes in there see if you can reproduce the error for both versions.

You can try and run mermaid server locally following these steps. Let me know after you try these, we need to report this to langchain and mermaid team.

  1. Download and run the mermaid container folowing instrutions here.
  2. From your python directory navigate to langchain_core/runnables/graph_mermaid.py/ > _render_mermaid_using_api() and replace https://mermaid.ink in image_url with `http://localhost:3000. Keep the rest of the url intact

Comments

0

One options is :

Image(graph.get_graph().draw_png())

before running above code :

!pip install pygraphviz

If you are using Colab :

!apt-get install -y graphviz libgraphviz-dev
!pip install pygraphviz

Comments

0

I was dealing with the same issue, but i just found the issue. I just found out it was syntax error with one of the nodes. Make sure your code works before you call the Image function.

Comments

-1

I faced the same issue. The inbuilt library (graph_mermaid.py) used by graph.py sometimes produces malformed URLs for Mermaid diagrams. Specifically, the function _render_mermaid_using_api handles encoding and sending Mermaid syntax to the API, which often fails due to Base64 encoding issues. You can modify this library to fix it, but it’s generally not recommended.

Instead, there are two practical solutions:


Option 1: Use Mermaid.ink with PNG output

import base64
import requests
from IPython.display import Image, display

def render_mermaid_png(mermaid_ascii: str, file_type="png", bg_color="white", output_file=None, max_retries=3):
    """
    Render a Mermaid diagram from ASCII code to PNG via mermaid.ink API.
    Handles URL-safe base64 encoding and proper padding.
    """
    # URL-safe base64 encode with proper padding
    b64 = base64.urlsafe_b64encode(mermaid_ascii.encode("utf-8")).decode("ascii")
    b64 += "=" * ((4 - len(b64) % 4) % 4)

    url = f"https://mermaid.ink/img/{b64}?type={file_type}&bgColor={bg_color}"

    for attempt in range(max_retries):
        try:
            resp = requests.get(url, timeout=10)
            resp.raise_for_status()
            img_bytes = resp.content
            if output_file:
                with open(output_file, "wb") as f:
                    f.write(img_bytes)
            display(Image(img_bytes))
            return
        except requests.RequestException as e:
            if attempt < max_retries - 1:
                continue
            else:
                raise RuntimeError(f"Failed to render Mermaid diagram: {e}\nURL: {url}")

# Usage:
mermaid_ascii = graph_builder.get_graph().draw_mermaid()
render_mermaid_png(mermaid_ascii)

Notes:

  • You can set background color via bg_color="white".

  • This method may fail if Mermaid.ink blocks your requests due to Cloudflare rate limits.


Option 2: Use Kroki.io as a fallback (recommended for reliability)

import zlib
import base64
import requests
from io import BytesIO
from PIL import Image as PILImage
from IPython.display import Image, display

def fetch_kroki_diagram(diagram_code: str, diagram_type="mermaid", file_type="png", max_retries=1) -> bytes:
    compressed = zlib.compress(diagram_code.encode("utf-8"))
    b64 = base64.urlsafe_b64encode(compressed).decode("ascii")
    url = f"https://kroki.io/{diagram_type}/{file_type}/{b64}"

    for attempt in range(max_retries):
        try:
            resp = requests.get(url, timeout=10)
            resp.raise_for_status()
            return resp.content
        except requests.RequestException as e:
            if attempt < max_retries - 1:
                continue
            else:
                raise RuntimeError(f"Failed to fetch diagram via Kroki: {e}\nURL: {url}")

# Generate Mermaid ASCII
mermaid_ascii = graph_builder.get_graph().draw_mermaid()

# Fetch PNG with white background
diagram_bytes = fetch_kroki_diagram(mermaid_ascii)

# Ensure white background if transparent
img = PILImage.open(BytesIO(diagram_bytes))
if img.mode in ("RGBA", "LA") or (img.mode == "P" and "transparency" in img.info):
    bg = PILImage.new("RGB", img.size, (255, 255, 255))
    bg.paste(img, mask=img.split()[3] if img.mode == "RGBA" else None)
    buf = BytesIO()
    bg.save(buf, format="PNG")
    diagram_bytes = buf.getvalue()

display(Image(diagram_bytes))

Why Kroki is better:

  • Bypasses Mermaid.ink Cloudflare blocks.

  • Supports both PNG and SVG output.

  • Reliable white background via ?bgColor=white.

  • Using SVG inline can disable other outputs in Jupyter/VS Code, so PNG is safer.

Attached image of output

enter image description here


References:


Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.