{"record":{"id":"39c42bfad9617436","repo":"langchain-ai/langchain","slug":"failed-to-reach-base-url-api-while-trying-to-ren-39c42b","errorCode":null,"errorMessage":"Failed to reach {base_url} API while trying to render your graph after {max_retries} retries. {error_msg_suffix}","messagePattern":"Failed to reach (.+?) API while trying to render your graph after (.+?) retries\\. (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/core/langchain_core/runnables/graph_mermaid.py","lineNumber":496,"sourceCode":"\n            # For other status codes, fail immediately\n            msg = (\n                f\"Failed to reach {base_url} API while trying to render \"\n                f\"your graph. Status code: {response.status_code}.\\n\\n\"\n            ) + error_msg_suffix\n            raise ValueError(msg)\n\n        except (requests.RequestException, requests.Timeout) as e:\n            if attempt < max_retries:\n                # Exponential backoff with jitter\n                sleep_time = retry_delay * (2**attempt) * (0.5 + 0.5 * random.random())  # noqa: S311 not used for crypto\n                time.sleep(sleep_time)\n            else:\n                msg = (\n                    f\"Failed to reach {base_url} API while trying to render \"\n                    f\"your graph after {max_retries} retries. \"\n                ) + error_msg_suffix\n                raise ValueError(msg) from e\n\n    # This should not be reached, but just in case\n    msg = (\n        f\"Failed to reach {base_url} API while trying to render \"\n        f\"your graph after {max_retries} retries. \"\n    ) + error_msg_suffix\n    raise ValueError(msg)\n","sourceCodeStart":478,"sourceCodeEnd":504,"githubUrl":"https://github.com/langchain-ai/langchain/blob/e32fa9a52eab3b61ad7a45399bfde59b3e580fc4/libs/core/langchain_core/runnables/graph_mermaid.py#L478-L504","documentation":"After exhausting max_retries on retryable failures, a requests.RequestException or Timeout escapes the retry loop and is re-raised as this ValueError (with `from e` preserving the cause). It means the Mermaid.INK endpoint (default https://mermaid.ink or your base_url) could not be reached at all or timed out on every attempt.","triggerScenarios":"draw_mermaid_png() with no internet, DNS failure, firewall blocking mermaid.ink, an unreachable self-hosted base_url, or timeouts with max_retries exhausted.","commonSituations":"Offline/air-gapped environments, containers with restricted egress, corporate proxies not configured, mermaid.ink temporarily down.","solutions":["Verify network access to the endpoint: curl -I https://mermaid.ink","Configure the proxy via the proxies argument or HTTPS_PROXY env var","Increase max_retries and retry_delay for flaky links","For offline use, self-host the mermaid.ink service and pass base_url, or switch to draw_method=MermaidDrawMethod.PYPPETEER with local Chromium"],"exampleFix":"# before\nimg = graph.draw_mermaid_png()  # network unreachable\n# after\nimg = graph.draw_mermaid_png(\n    max_retries=3,\n    retry_delay=2.0,\n    base_url=\"https://your-internal-mermaid\",\n)","handlingStrategy":"retry","validationCode":"import socket\nsocket.getaddrinfo(\"mermaid.ink\", 443)  # fail fast if DNS/egress blocked","typeGuard":null,"tryCatchPattern":"try:\n    img = draw_mermaid_png(syntax, max_retries=3, retry_delay=2.0)\nexcept ValueError as e:\n    if \"after\" in str(e) and \"retries\" in str(e):\n        img = render_locally_with_pyppeteer(syntax)  # offline fallback","preventionTips":["Set max_retries >= 2 and retry_delay for flaky networks","Pin a reachable base_url (self-hosted) in air-gapped deployments"],"tags":["graph","mermaid","network","timeout","retry","valueerror"],"backgroundTag":null,"analyzedSha":"e32fa9a52eab3b61ad7a45399bfde59b3e580fc4","analyzedAt":"2026-08-14T18:42:09.092Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}