garrytan/gstack · error

excalidraw scene has no elements array

Error message

excalidraw scene has no elements array

What it means

Thrown by __excalidrawToSvg() when the parsed scene JSON does not have an Array at scene.elements. exportToSvg requires a real array of element objects, so a missing or wrongly-typed elements field would either throw deeper or render nothing; this guard fails early with a clear message. The function deliberately does not coerce — callers must pass a valid Excalidraw scene.

Source

Thrown at lib/diagram-render/src/entry.ts:88

};

window.__mermaidToExcalidraw = async (text: string): Promise<string> => {
  const { elements, files } = await parseMermaidToExcalidraw(text);
  const converted = convertToExcalidrawElements(elements);
  const scene = {
    type: "excalidraw",
    version: 2,
    source: "gstack-diagram-render",
    elements: converted,
    appState: { viewBackgroundColor: "#ffffff" },
    files: files ?? {},
  };
  return JSON.stringify(scene);
};

window.__excalidrawToSvg = async (sceneJson: string): Promise<string> => {
  const scene = JSON.parse(sceneJson);
  if (!Array.isArray(scene.elements)) throw new Error("excalidraw scene has no elements array");
  const svg = await exportToSvg({
    elements: scene.elements,
    appState: { ...(scene.appState ?? {}), exportBackground: true },
    files: scene.files ?? null,
    exportPadding: 16,
  });
  return new XMLSerializer().serializeToString(svg);
};

/**
 * SVG → PNG data URL at an explicit pixel width. Callers own the DPI math:
 * targetWidthPx = placed physical width (in) × 300dpi (eng-review D6.5) —
 * the bundle never guesses a viewport.
 */
/** Shared ceiling for rasterization targets (both window functions). */
const MAX_TARGET_PX = 10_000;
function assertTargetWidth(px: number): void {
  if (!(px > 0 && px <= MAX_TARGET_PX)) {

View on GitHub (pinned to 94993f7401)

Solutions

  1. Validate the scene has elements as an array before calling — log the parsed object to inspect.
  2. If producing scenes programmatically, always include elements: [...].
  3. Ensure you are passing output from __mermaidToExcalidraw, not raw mermaid text.
  4. If the payload was truncated in transit, re-serialize the full scene.

Example fix

// before
__excalidrawToSvg(JSON.stringify({ type: 'excalidraw' }));

// after
__excalidrawToSvg(JSON.stringify({ type: 'excalidraw', elements: [], appState: {}, files: {} }));
Defensive patterns

Strategy: type-guard

Validate before calling

function assertExcalidrawScene(sceneJson: string): void {
  const scene = JSON.parse(sceneJson);
  if (!Array.isArray(scene.elements)) {
    throw new Error('Pass a valid Excalidraw scene: { type, elements: [], appState, files }');
  }
}

Type guard

function isExcalidrawScene(v: unknown): v is { elements: unknown[]; [k: string]: unknown } {
  return typeof v === 'object' && v !== null && Array.isArray((v as any).elements);
}

Prevention

When it happens

Trigger: Call window.__excalidrawToSvg(sceneJson) where sceneJson parses to an object whose elements is undefined, null, an object, a string, or absent entirely. Happens if the upstream __mermaidToExcalidraw output is mangled, a hand-built scene omits elements, or the wrong JSON is passed.

Common situations: Caller passes a mermaid text string instead of a scene object; a pipeline stage stripped elements during transformation; version-skew between the scene producer and this renderer; corrupted JSON.parse of a truncated payload.

Related errors


AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12). Data as JSON: /api/errors/11cfbe500bd995bc. Report an issue: GitHub.