{"record":{"id":"d1736b09a2cd54d8","repo":"garrytan/gstack","slug":"targetwidthpx-out-of-range-px","errorCode":null,"errorMessage":"targetWidthPx out of range: ${px}","messagePattern":"targetWidthPx out of range: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/diagram-render/src/entry.ts","lineNumber":107,"sourceCode":"  const svg = await exportToSvg({\n    elements: scene.elements,\n    appState: { ...(scene.appState ?? {}), exportBackground: true },\n    files: scene.files ?? null,\n    exportPadding: 16,\n  });\n  return new XMLSerializer().serializeToString(svg);\n};\n\n/**\n * SVG → PNG data URL at an explicit pixel width. Callers own the DPI math:\n * targetWidthPx = placed physical width (in) × 300dpi (eng-review D6.5) —\n * the bundle never guesses a viewport.\n */\n/** Shared ceiling for rasterization targets (both window functions). */\nconst MAX_TARGET_PX = 10_000;\nfunction assertTargetWidth(px: number): void {\n  if (!(px > 0 && px <= MAX_TARGET_PX)) {\n    throw new Error(`targetWidthPx out of range: ${px}`);\n  }\n}\n\nwindow.__rasterize = async (svgText: string, targetWidthPx: number): Promise<string> => {\n  assertTargetWidth(targetWidthPx);\n  const blob = new Blob([svgText], { type: \"image/svg+xml;charset=utf-8\" });\n  const url = URL.createObjectURL(blob);\n  try {\n    const img = new Image();\n    await new Promise<void>((resolve, reject) => {\n      img.onload = () => resolve();\n      img.onerror = () => reject(new Error(\"SVG image decode failed (malformed SVG or foreignObject content)\"));\n      img.src = url;\n    });\n    const naturalW = img.naturalWidth || 800;\n    const naturalH = img.naturalHeight || 600;\n    const scale = targetWidthPx / naturalW;\n    const canvas = document.createElement(\"canvas\");","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/lib/diagram-render/src/entry.ts#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n__rasterize(svg, pageWidthInches * 300); // pageWidthInches could be 0\n\n// after\nconst px = Number.isFinite(pageWidthInches) && pageWidthInches > 0 ? pageWidthInches * 300 : 800;\n__rasterize(svg, Math.min(px, 10000));","handlingStrategy":"validation","validationCode":"const MAX_TARGET_PX = 10_000;\nfunction clampTargetWidth(px: number): number {\n  if (!Number.isFinite(px) || px <= 0) return 800;\n  return Math.min(px, MAX_TARGET_PX);\n}","typeGuard":"function isValidTargetWidth(px: number): boolean {\n  return typeof px === 'number' && Number.isFinite(px) && px > 0 && px <= 10_000;\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["diagram-render","rasterization","validation","canvas"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}