{"record":{"id":"dccd25942783c8b1","repo":"danny-avila/LibreChat","slug":"failed-to-load-mermaid-library","errorCode":null,"errorMessage":"Failed to load mermaid library","messagePattern":"Failed to load mermaid library","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"client/src/hooks/Mermaid/useMermaid.ts","lineNumber":116,"sourceCode":"      securityLevel: 'strict',\n      maxTextSize: config?.maxTextSize ?? 50000,\n      maxEdges: config?.maxEdges ?? 500,\n    };\n  }, [customTheme, isDarkMode, config]);\n\n  // Fetch/render function\n  const fetchSvg = async (): Promise<string> => {\n    // SSR guard\n    if (typeof window === 'undefined') {\n      return '';\n    }\n\n    try {\n      // Load mermaid library (cached after first load)\n      const mermaidInstance = await loadMermaid();\n\n      if (!mermaidInstance) {\n        throw new Error('Failed to load mermaid library');\n      }\n\n      // Validate syntax first and capture detailed error\n      try {\n        await mermaidInstance.parse(content);\n      } catch (parseError) {\n        // Extract meaningful error message from mermaid's parse error\n        let errorMessage = 'Invalid mermaid syntax';\n        if (parseError instanceof Error) {\n          errorMessage = parseError.message;\n        } else if (typeof parseError === 'string') {\n          errorMessage = parseError;\n        }\n\n        throw new Error(errorMessage);\n      }\n\n      // Initialize with config","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/client/src/hooks/Mermaid/useMermaid.ts#L98-L134","documentation":"Thrown by the Mermaid render hook when `loadMermaid()` resolves to a falsy value. `loadMermaid` returns `null` in two situations: during SSR (`typeof window === 'undefined'`), or when the dynamic `import('mermaid')` rejects. Note that `loadMermaid` caches its promise in a module-level variable — if the import fails once, every subsequent call reuses the same rejected promise until a full page reload resets the module.","triggerScenarios":"The Mermaid code block tries to render during server-side rendering (Next.js SSR) where `window` is undefined; the browser cannot load the `mermaid` chunk (network failure, ad blocker/ CSP blocking the dynamic import, chunk hash mismatch after a redeploy); the mermaid package is missing or mis-versioned in the build.","commonSituations":"Deploying a new build while users hold an old one (chunk not found / stale hash); strict CSP without `script-src` allowing the bundled chunk; offline/poor connectivity during first Mermaid render (the ~2MB chunk fails to load); SSR/SSG rendering message content that includes Mermaid blocks; ad-blockers stripping the dynamic import.","solutions":["If SSR: skip rendering on the server (the hook already returns `''` when window is undefined — ensure the component doesn't call `fetchSvg` during SSR).","If the chunk fails to load at runtime: hard-reload the page to clear the cached rejected promise and fetch the current chunk.","Ensure `mermaid` is a real dependency (not optional/peer) and the bundler emits its chunk; check the Network tab for a failed chunk request.","Relax CSP `script-src`/`connect-src` to allow the bundled chunk, or exclude ad-blockers from the domain."],"exampleFix":"// before\nconst mermaidInstance = await loadMermaid();\nif (!mermaidInstance) {\n  throw new Error('Failed to load mermaid library');\n}\n// after — reset the cached promise on failure so a retry can succeed\nconst loadMermaid = () => {\n  if (typeof window === 'undefined') return Promise.resolve(null);\n  if (!mermaidPromise) {\n    mermaidPromise = import('mermaid').then((m) => m.default).catch((e) => {\n      mermaidPromise = null; // allow next call to retry\n      throw e;\n    });\n  }\n  return mermaidPromise;\n};","handlingStrategy":"fallback","validationCode":"// Skip Mermaid rendering outside the browser\nif (typeof window === 'undefined') return null; // don't call fetchSvg during SSR","typeGuard":"function isMermaidLoaded(m: unknown): m is typeof import('mermaid').default {\n  return m != null && typeof (m as any).parse === 'function' && typeof (m as any).render === 'function';\n}","tryCatchPattern":"try {\n  const mermaid = await loadMermaid();\n  if (!mermaid) throw new Error('Failed to load mermaid library');\n} catch (err) {\n  setValidContent(null); // show fallback / raw source instead of crashing the message\n}","preventionTips":["Don't invoke Mermaid rendering during SSR — gate on `typeof window !== 'undefined'`.","Reset the cached import promise on rejection so a retry can fetch the chunk again (see exampleFix).","Ensure CSP allows the Mermaid chunk and that `mermaid` is a real dependency.","Prompt users to hard-reload after a deployment that changes chunk hashes."],"tags":["mermaid","dynamic-import","ssr","browser","chunk-loading","diagrams"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}