garrytan/gstack · warning · StrictModeError

image exceeds ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB

Error message

image exceeds ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB cap: ${src} (${Math.round(stat.size / 1024 / 1024)}MB)

What it means

StrictModeError thrown when a local image file is a regular file but its byte size exceeds MAX_IMAGE_BYTES. The cap bounds memory before any readFileSync, preventing a multi-GB image from exhausting memory. Non-strict mode warns and substitutes a placeholder; strict makes it fatal. The message shows both the cap (MB) and the actual size (MB).

Source

Thrown at make-pdf/src/diagram-prepass.ts:673

    // Bound the read BEFORE reading: a markdown image pointing at a special
    // file (fifo, device) would hang readFileSync, and a multi-GB file would
    // exhaust memory before any policy ran.
    let stat: fs.Stats;
    try {
      stat = fs.statSync(filePath);
    } catch {
      opts.warn(`image unreadable: ${src}`);
      return buildMissingImagePlaceholder(src);
    }
    if (!stat.isFile()) {
      const msg = `image is not a regular file: ${src}`;
      if (opts.strict) throw new StrictModeError(msg);
      opts.warn(msg);
      return buildMissingImagePlaceholder(src);
    }
    if (stat.size > MAX_IMAGE_BYTES) {
      const msg = `image exceeds ${Math.round(MAX_IMAGE_BYTES / 1024 / 1024)}MB cap: ${src} (${Math.round(stat.size / 1024 / 1024)}MB)`;
      if (opts.strict) throw new StrictModeError(msg);
      opts.warn(msg);
      return buildMissingImagePlaceholder(src);
    }

    let buf = fs.readFileSync(filePath);
    let dims = imageDims(buf);
    let mime = dims?.mime ?? mimeFromExtension(filePath);

    // Print-resolution normalization (D4): rasters only — SVG scales free.
    if (dims && mime !== "image/svg+xml" && dims.width > maxPx) {
      const tab = opts.getTab();
      if (tab) {
        try {
          const dataUri = `data:${mime};base64,${buf.toString("base64")}`;
          const scaled = tab.call("__downscaleRaster", dataUri, targetPx, mime);
          const scaledB64 = scaled.replace(/^data:[^,]*,/, "");
          opts.warn(
            `downscaled ${path.basename(filePath)} ${dims.width}px → ${targetPx}px ` +

View on GitHub (pinned to 94993f7401)

Solutions

  1. Downscale/compress the image below MAX_IMAGE_BYTES (e.g. `convert big.png -resize 50% big.png`).
  2. Reference a smaller, web-resolution variant of the image.
  3. Drop --strict to degrade to a warn + placeholder.
  4. If the large image is intentional and print resolution matters, raise MAX_IMAGE_BYTES in a fork after verifying available memory.

Example fix

# before
$ make-pdf --strict report.md  # image is 180MB
Error: image exceeds 64MB cap: ./assets/poster.png (180MB)

# after: downscale
$ convert ./assets/poster.png -resize 25% ./assets/poster.png
$ make-pdf --strict report.md
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
import path from 'node:path';

const MAX_IMAGE_BYTES = 64 * 1024 * 1024; // match the library constant
function findOversizedImages(markdown: string, inputDir: string): { src: string; size: number }[] {
  const re = /!\[[^\]]*\]\((?!https?:|data:)([^)]+)\)/g;
  const big: { src: string; size: number }[] = [];
  let m: RegExpExecArray | null;
  while ((m = re.exec(markdown))) {
    const p = path.resolve(inputDir, decodeURIComponent(m[1]));
    try { const s = fs.statSync(p); if (s.isFile() && s.size > MAX_IMAGE_BYTES) big.push({ src: m[1], size: s.size }); } catch {}
  }
  return big;
}

Type guard

import { StrictModeError } from './diagram-prepass';
function isStrictModeError(e: unknown): e is StrictModeError {
  return e instanceof StrictModeError;
}

Prevention

When it happens

Trigger: inlineLocalImages() under --strict where fs.statSync(filePath).size > MAX_IMAGE_BYTES. Typical with a raw camera TIFF, an uncompressed scan, or a mistakenly-referenced video file with an image extension.

Common situations: A designer committed a 200MB PSD exported as PNG; a doc references a print-resolution 300DPI A0 poster; an asset混淆 with a .png-named data dump; a CI machine with limited RAM hitting OOM before this guard existed.

Related errors


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