Stirling-Tools/Stirling-PDF · error · Error

PDFium: failed to create page

Error message

PDFium: failed to create page

What it means

`PdfiumDocument.addPage(dimensions)` calls `FPDFPage_New(docPtr, index, width, height)`. A null return means page creation failed. Unlike document creation, page creation has a concrete precondition: `width`/`height` must be positive finite numbers within PDFium's coordinate range. Zero, negative, NaN, Infinity, or astronomically large values make PDFium refuse the page.

Source

Thrown at frontend/editor/src/core/services/pdfiumDocBuilder.ts:364

  /** Create a new empty PDF document. Drop-in replacement for `PDFDocument.create()`. */
  static async create(): Promise<PdfiumDocument> {
    const m = await getPdfiumModule();
    const docPtr = m.FPDF_CreateNewDocument();
    if (!docPtr) throw new Error("PDFium: failed to create document");
    return new PdfiumDocument(m, docPtr);
  }

  /** Add a new page to the document. */
  addPage(dimensions: [number, number]): PdfiumPage {
    const [width, height] = dimensions;
    const insertIdx = this._pages.length;
    const pagePtr = this._m.FPDFPage_New(
      this._docPtr,
      insertIdx,
      width,
      height,
    );
    if (!pagePtr) throw new Error("PDFium: failed to create page");
    const page = new PdfiumPage(this._m, this._docPtr, pagePtr, width, height);
    this._pages.push(page);
    return page;
  }

  /** Embed a standard PDF font. Returns a PdfiumFont for text measurement and drawing. */
  async embedFont(fontName: string): Promise<PdfiumFont> {
    if (this._fonts.has(fontName)) return this._fonts.get(fontName)!;
    const font = new PdfiumFont(fontName);
    this._fonts.set(fontName, font);
    return font;
  }

  /** Embed a PNG image from raw bytes. */
  async embedPng(bytes: Uint8Array | ArrayBuffer): Promise<PdfiumImage> {
    return this._decodeImage(
      bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes),
      "image/png",

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Validate dimensions before calling `addPage`: `Number.isFinite(width) && Number.isFinite(height) && width > 0 && height > 0`, clamping to sane bounds (e.g. 1–14400 pt).
  2. Guard against using a disposed document: track a `_disposed` flag and throw a clearer error if `addPage` is called after `dispose()`.
  3. On null pagePtr, call `FPDF_GetLastError()` to capture the reason (this code currently does not).
  4. Audit upstream callers for unguarded `parseFloat`/division that could yield NaN.

Example fix

// before
addPage(dimensions: [number, number]): PdfiumPage {
  const [width, height] = dimensions;
  const insertIdx = this._pages.length;
  const pagePtr = this._m.FPDFPage_New(this._docPtr, insertIdx, width, height);
  if (!pagePtr) throw new Error("PDFium: failed to create page");
  ...
}

// after
addPage(dimensions: [number, number]): PdfiumPage {
  const [width, height] = dimensions;
  if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
    throw new Error(`PdfiumDocument.addPage: invalid dimensions [${width}, ${height}]`);
  }
  const insertIdx = this._pages.length;
  const pagePtr = this._m.FPDFPage_New(this._docPtr, insertIdx, width, height);
  if (!pagePtr) {
    const err = this._m.FPDF_GetLastError?.() ?? "unknown";
    throw new Error(`PDFium: failed to create page (error ${err})`);
  }
  ...
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate dimensions before addPage
function validDims(w: number, h: number): boolean {
  return Number.isFinite(w) && Number.isFinite(h) && w > 0 && h > 0 && w <= 14400 && h <= 14400;
}

Type guard

function isFinitePositiveDimensions(d: [number, number]): boolean {
  return Array.isArray(d) && d.length === 2 && d.every(n => Number.isFinite(n) && n > 0);
}

Try / catch

try {
  doc.addPage([w, h]);
} catch (e) {
  if (e instanceof Error && /invalid dimensions/.test(e.message)) {
    doc.addPage([595.276, 841.89]); // fall back to A4
  } else throw e;
}

Prevention

When it happens

Trigger: Passing `[0, 0]`, negative dimensions, `NaN` (e.g. from a failed `parseFloat`), `Infinity`, or values outside PDFium's expected point range; calling `addPage` after the document pointer was closed/corrupted; WASM heap exhaustion at page allocation.

Common situations: Page dimensions sourced from a malformed PDF page object (e.g. a corrupt `getViewport` returning 0); a calculation that divided by zero; using a closed `PdfiumDocument` whose `_docPtr` was already freed.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/7a0480f5332e6c83. Report an issue: GitHub.