Stirling-Tools/Stirling-PDF · error · Error

Failed to create link annotation

Error message

Failed to create link annotation

What it means

Thrown in createLinkAnnotation when m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK) returns a falsy pointer. By this point the page loaded successfully, so a null annotation pointer indicates PDFium ran out of WASM memory, the page object is internally inconsistent, or the annotation subsystem could not allocate. This is rare and usually points to resource exhaustion or a corrupt page.

Source

Thrown at frontend/editor/src/core/utils/pdfLinkUtils.ts:129

    const pageCount = m.FPDF_GetPageCount(docPtr);
    if (
      destinationPage !== undefined &&
      (destinationPage < 0 || destinationPage >= pageCount)
    ) {
      throw new RangeError(
        `createLinkAnnotation: destinationPage ${destinationPage} out of range [0, ${pageCount})`,
      );
    }

    const pagePtr = m.FPDF_LoadPage(docPtr, pageIndex);
    if (!pagePtr) throw new Error(`Failed to load page ${pageIndex}`);

    try {
      const pageHeight = m.FPDF_GetPageHeightF(pagePtr);

      const annotPtr = m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK);
      if (!annotPtr) {
        throw new Error("Failed to create link annotation");
      }

      try {
        // Set rect (convert from CSS top-left to PDF bottom-left origin)
        // FS_RECTF layout: { left, top, right, bottom } where top > bottom in PDF coords
        const pdfLeft = rect.x;
        const pdfTop = pageHeight - rect.y; // CSS y=0 → PDF top
        const pdfRight = rect.x + rect.width;
        const pdfBottom = pageHeight - rect.y - rect.height; // CSS bottom → PDF bottom

        const rectBuf = m.pdfium.wasmExports.malloc(4 * 4);
        m.pdfium.setValue(rectBuf, pdfLeft, "float"); // offset 0: left
        m.pdfium.setValue(rectBuf + 4, pdfTop, "float"); // offset 4: top  (larger y)
        m.pdfium.setValue(rectBuf + 8, pdfRight, "float"); // offset 8: right
        m.pdfium.setValue(rectBuf + 12, pdfBottom, "float"); // offset 12: bottom (smaller y)
        m.FPDFAnnot_SetRect(annotPtr, rectBuf);
        m.pdfium.wasmExports.free(rectBuf);

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Ensure the WASM module has sufficient heap (avoid large simultaneous buffers; free with closeDocAndFreeBuffer promptly).
  2. Rate-limit bulk annotation creation and verify each annotation pointer before continuing.
  3. On failure, abort the transaction rather than continuing with a partial set of annotations.
  4. Re-open the document and retry once; if it persists, report the page as uneditable.

Example fix

// before
const annotPtr = m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK);
if (!annotPtr) throw new Error("Failed to create link annotation");

// after
const annotPtr = m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK);
if (!annotPtr) {
  throw new Error(
    "Failed to create link annotation: PDFium could not allocate the annotation (possible WASM memory exhaustion or corrupt page).",
  );
}
Defensive patterns

Strategy: retry

Validate before calling

// No pure pre-check exists for PDFium annotation allocation; budget the heap instead.
// Ensure prior buffers are freed and keep a single open document at a time.

Prevention

When it happens

Trigger: Creating many annotations in a loop until WASM heap is exhausted; a malformed page object that loads but rejects annotation creation; concurrent annotation operations on the same module without synchronization.

Common situations: Bulk link-annotation workflows on large PDFs; low-memory devices; PDFs with broken annotation dictionaries already present.

Related errors


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