danny-avila/LibreChat · error · Error
Canvas is unavailable for Mermaid PNG export
Error message
Canvas is unavailable for Mermaid PNG export
What it means
Thrown by the PNG export path when `document.createElement('canvas').getContext('2d')` returns null. A null 2D context means the browser either does not expose the Canvas 2D API or has exhausted its per-page context limit (browsers cap simultaneous WebGL/2D contexts; exceeding it returns null for new ones). This is rare in modern browsers but real in constrained/headless environments.
Source
Thrown at client/src/utils/diagram/export.ts:229
triggerDownload(url, exportFilename(filename, 'svg'));
}
export async function downloadMermaidPng(
svg: string,
filename: string,
dimensions?: MermaidDimensions | null,
background?: string,
): Promise<void> {
const sourceUrl = await blobDataUrl(svgBlob(svg));
const image = await loadSvgImage(sourceUrl);
const sourceWidth = dimensions?.width || image.naturalWidth || image.width;
const sourceHeight = dimensions?.height || image.naturalHeight || image.height;
const canvasDimensions = resolveCanvasDimensions(sourceWidth, sourceHeight);
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
if (!context) {
throw new Error('Canvas is unavailable for Mermaid PNG export');
}
canvas.width = canvasDimensions.width;
canvas.height = canvasDimensions.height;
context.imageSmoothingEnabled = true;
context.imageSmoothingQuality = 'high';
if (background) {
context.fillStyle = background;
context.fillRect(0, 0, canvas.width, canvas.height);
}
context.drawImage(image, 0, 0, canvas.width, canvas.height);
const png = await encodePng(canvas);
const outputUrl = URL.createObjectURL(png);
triggerDownload(outputUrl, exportFilename(filename, 'png'));
}
View on GitHub (pinned to 5ff282f900)
Solutions
- In tests, install/configure the `canvas` package for jsdom, or mock `downloadMermaidPng`.
- In production, free unused canvas contexts (set width/height to 0 and let them be GC'd) to avoid hitting the per-page context cap.
- Detect the null context and fall back to SVG export (or a server-side rasterization) instead of failing.
- If a fingerprinting shield is the cause, document that PNG export requires canvas and offer SVG download as an alternative.
Example fix
// before
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
if (!context) {
throw new Error('Canvas is unavailable for Mermaid PNG export');
}
// after — fall back to SVG download when a 2D context cannot be obtained
const context = canvas.getContext('2d');
if (!context) {
logger.warn('Canvas 2D unavailable; falling back to SVG export');
return downloadMermaidSvg(svg, filename);
} Defensive patterns
Strategy: fallback
Validate before calling
// Probe canvas 2D support before offering PNG export
function canvas2dAvailable(): boolean {
try {
return !!document.createElement('canvas').getContext('2d');
} catch { return false; }
} Type guard
function hasCanvas2D(): boolean {
if (typeof document === 'undefined') return false;
const c = document.createElement('canvas');
return c.getContext('2d') != null;
} Try / catch
const context = canvas.getContext('2d');
if (!context) {
// Fall back to SVG download instead of failing the export entirely
return downloadMermaidSvg(svg, filename);
} Prevention
- Free unused canvas contexts (resize to 0) to avoid hitting the per-page context cap.
- Offer SVG download as a fallback when canvas is unavailable (privacy browsers, jsdom).
- In jsdom tests, install/configure the `canvas` package or mock `downloadMermaidPng`.
When it happens
Trigger: Running the export in a headless test runner (jsdom) that does not implement `canvas.getContext('2d')` without the `canvas` npm package; a page that leaked many canvas contexts and hit the browser limit; an embedded WebView/older browser without 2D canvas; a hardening extension that blocks canvas (fingerprinting protection returning null).
Common situations: Unit/integration tests under jsdom without canvas polyfill; privacy browsers/extensions (Brave, Tor, fingerprinting shields) that neuter canvas; long-lived SPA that created hundreds of canvases; embedded WebView in a native app with limited canvas support.
Related errors
- Mermaid diagram has invalid export dimensions
- Failed to get response reader
- Failed to load mermaid library
- Invalid mermaid syntax
AI-assisted analysis of danny-avila/LibreChat@5ff282f900 (2026-08-12).
Data as JSON: /api/errors/de16bb3411d518c2.
Report an issue: GitHub.