garrytan/gstack · error · Error

targetWidthPx out of range: ${px}

Error message

targetWidthPx out of range: ${px}

What it means

Thrown by assertTargetWidth() when the requested rasterization width px is not in the range (0, 10000]. Both __rasterize and __downscaleRaster call this guard so callers cannot request zero, negative, NaN, or absurdly large canvases that would exhaust memory. The ceiling MAX_TARGET_PX = 10_000 caps canvas allocation; the floor excludes degenerate non-output. Callers own the DPI math, so this is the bundle's only width sanity check.

Source

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

  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)) {
    throw new Error(`targetWidthPx out of range: ${px}`);
  }
}

window.__rasterize = async (svgText: string, targetWidthPx: number): Promise<string> => {
  assertTargetWidth(targetWidthPx);
  const blob = new Blob([svgText], { type: "image/svg+xml;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  try {
    const img = new Image();
    await new Promise<void>((resolve, reject) => {
      img.onload = () => resolve();
      img.onerror = () => reject(new Error("SVG image decode failed (malformed SVG or foreignObject content)"));
      img.src = url;
    });
    const naturalW = img.naturalWidth || 800;
    const naturalH = img.naturalHeight || 600;
    const scale = targetWidthPx / naturalW;
    const canvas = document.createElement("canvas");

View on GitHub (pinned to 94993f7401)

Solutions

  1. Compute targetWidthPx = placedPhysicalWidthInches * 300 and ensure placedPhysicalWidthInches is a positive finite number.
  2. Clamp the value: Math.min(Math.max(px, 1), 10000) before calling if a fallback is acceptable.
  3. If you legitimately need >10000px, rasterize in tiles or use __mountForScreenshot + a screenshot tool instead.
  4. Check for NaN by guarding Number.isFinite(px) before the call.

Example fix

// before
__rasterize(svg, pageWidthInches * 300); // pageWidthInches could be 0

// after
const px = Number.isFinite(pageWidthInches) && pageWidthInches > 0 ? pageWidthInches * 300 : 800;
__rasterize(svg, Math.min(px, 10000));
Defensive patterns

Strategy: validation

Validate before calling

const MAX_TARGET_PX = 10_000;
function clampTargetWidth(px: number): number {
  if (!Number.isFinite(px) || px <= 0) return 800;
  return Math.min(px, MAX_TARGET_PX);
}

Type guard

function isValidTargetWidth(px: number): boolean {
  return typeof px === 'number' && Number.isFinite(px) && px > 0 && px <= 10_000;
}

Prevention

When it happens

Trigger: Call __rasterize or __downscaleRaster with targetWidthPx of 0, a negative number, NaN, undefined (coerced to NaN), or a value > 10000. Common when DPI math computes width = placed_inches * 300 and placed_inches is 0 or missing.

Common situations: Caller passed undefined/0 because the document layout hadn't measured the element width yet; DPI multiplier produced an enormous width for a full-bleed page; arithmetic bug producing NaN; intentionally requesting a huge poster size beyond the cap.

Related errors


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