AykutSarac/jsoncrack.com · error
Canvas not found.
Error message
Canvas not found.
What it means
Toast from clipboardImage() when getExportElement() returns null. getExportElement queries the DOM for `.jsoncrack-canvas` first, falling back to `svg[id*='ref']`. If neither exists (the graph canvas was not rendered, was unmounted, or uses a different selector in an integration), the clipboard copy aborts.
Source
Thrown at apps/www/src/features/modals/DownloadModal/index.tsx:83
const getExportElement = () =>
(document.querySelector(".jsoncrack-canvas") as HTMLElement | null) ??
(document.querySelector("svg[id*='ref']") as HTMLElement | null);
export const DownloadModal = ({ opened, onClose }: ModalProps) => {
const [extension, setExtension] = React.useState(Extensions.PNG);
const [fileDetails, setFileDetails] = React.useState({
filename: "jsoncrack.com",
backgroundColor: "#FFFFFF",
quality: 1,
});
const clipboardImage = async () => {
try {
toast.loading("Copying to clipboard...", { id: "toastClipboard" });
const imageElement = getExportElement();
if (!imageElement) {
toast.error("Canvas not found.");
return;
}
const imageOptions = {
quality: fileDetails.quality,
backgroundColor: fileDetails.backgroundColor,
skipFonts: true,
};
const blob = await toBlob(imageElement, imageOptions);
if (!blob) return;
await navigator.clipboard?.write([
new ClipboardItem({
[blob.type]: blob,
}),
]);
View on GitHub (pinned to 3c9af69e23)
Solutions
- Ensure the graph has rendered before enabling the Clipboard button (gate on a non-empty canvas).
- Confirm the canvas wrapper retains the `jsoncrack-canvas` class.
- Wait for layout/onLayoutChange before allowing export.
- If integrating, render the component so that `.jsoncrack-canvas` or an `svg[id*='ref']` exists in the DOM.
Example fix
// before
const imageElement = getExportElement();
if (!imageElement) {
toast.error("Canvas not found.");
return;
}
// after — retry once after a frame to tolerate not-yet-painted canvas
const waitFrame = () => new Promise(r => requestAnimationFrame(() => r(null)));
let imageElement = getExportElement();
if (!imageElement) { await waitFrame(); imageElement = getExportElement(); }
if (!imageElement) {
toast.error("Canvas not found. Wait for the graph to render first.");
return;
} Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure the export target exists in the DOM before enabling Clipboard
export function canvasReady(): boolean {
return !!(document.querySelector(".jsoncrack-canvas") || document.querySelector("svg[id*='ref']"));
} Type guard
// Treat getExportElement's result as a present HTMLElement
function isExportElement(el: Element | null): el is HTMLElement {
return el instanceof HTMLElement;
} Try / catch
// Guard, then act; offer a user-actionable hint
const el = getExportElement();
if (!el) {
toast.error("Canvas not found. Wait for the graph to render.");
return;
} Prevention
- Gate the Clipboard button on layout readiness.
- Keep the `.jsoncrack-canvas` class on the canvas wrapper.
- Wait for onLayoutChange before allowing export.
When it happens
Trigger: Opening the Download modal before the graph has rendered; the canvas unmounted due to an error/empty input; embedding JSONCrack with a custom className that replaced `.jsoncrack-canvas`; an integration that does not render the reaflow Canvas.
Common situations: Clicking 'Clipboard' immediately on modal open before layout completes; calling export on an empty/above-limit graph (no canvas rendered); DOM stripped by an error boundary.
Related errors
- Failed to copy to clipboard
- Clipboard write permission denied. Please allow clipboard ac
- Failed to download image!
- Invalid Schema
- error.message
AI-assisted analysis of AykutSarac/jsoncrack.com@3c9af69e23 (2026-08-12).
Data as JSON: /api/errors/090b26363b02dad8.
Report an issue: GitHub.