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
- Compute targetWidthPx = placedPhysicalWidthInches * 300 and ensure placedPhysicalWidthInches is a positive finite number.
- Clamp the value: Math.min(Math.max(px, 1), 10000) before calling if a fallback is acceptable.
- If you legitimately need >10000px, rasterize in tiles or use __mountForScreenshot + a screenshot tool instead.
- 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
- Compute px from a validated physical width: px = inches * 300.
- Guard Number.isFinite(px) before the call.
- Clamp very large page widths to MAX_TARGET_PX.
- Document the (0, 10000] contract in every caller of __rasterize/__downscaleRaster.
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
- 2d canvas context unavailable
- invalid mermaid render id: ${id}
- excalidraw scene has no elements array
- Skill name is empty.
- Invalid skill name "${name}". Must be lowercase letters/digi
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/d1736b09a2cd54d8.
Report an issue: GitHub.