{"record":{"id":"225c76f4fe8d32bf","repo":"Stirling-Tools/Stirling-PDF","slug":"failed-to-create-link-annotation","errorCode":null,"errorMessage":"Failed to create link annotation","messagePattern":"Failed to create link annotation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/utils/pdfLinkUtils.ts","lineNumber":129,"sourceCode":"    const pageCount = m.FPDF_GetPageCount(docPtr);\n    if (\n      destinationPage !== undefined &&\n      (destinationPage < 0 || destinationPage >= pageCount)\n    ) {\n      throw new RangeError(\n        `createLinkAnnotation: destinationPage ${destinationPage} out of range [0, ${pageCount})`,\n      );\n    }\n\n    const pagePtr = m.FPDF_LoadPage(docPtr, pageIndex);\n    if (!pagePtr) throw new Error(`Failed to load page ${pageIndex}`);\n\n    try {\n      const pageHeight = m.FPDF_GetPageHeightF(pagePtr);\n\n      const annotPtr = m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK);\n      if (!annotPtr) {\n        throw new Error(\"Failed to create link annotation\");\n      }\n\n      try {\n        // Set rect (convert from CSS top-left to PDF bottom-left origin)\n        // FS_RECTF layout: { left, top, right, bottom } where top > bottom in PDF coords\n        const pdfLeft = rect.x;\n        const pdfTop = pageHeight - rect.y; // CSS y=0 → PDF top\n        const pdfRight = rect.x + rect.width;\n        const pdfBottom = pageHeight - rect.y - rect.height; // CSS bottom → PDF bottom\n\n        const rectBuf = m.pdfium.wasmExports.malloc(4 * 4);\n        m.pdfium.setValue(rectBuf, pdfLeft, \"float\"); // offset 0: left\n        m.pdfium.setValue(rectBuf + 4, pdfTop, \"float\"); // offset 4: top  (larger y)\n        m.pdfium.setValue(rectBuf + 8, pdfRight, \"float\"); // offset 8: right\n        m.pdfium.setValue(rectBuf + 12, pdfBottom, \"float\"); // offset 12: bottom (smaller y)\n        m.FPDFAnnot_SetRect(annotPtr, rectBuf);\n        m.pdfium.wasmExports.free(rectBuf);\n","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/utils/pdfLinkUtils.ts#L111-L147","documentation":"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.","triggerScenarios":"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.","commonSituations":"Bulk link-annotation workflows on large PDFs; low-memory devices; PDFs with broken annotation dictionaries already present.","solutions":["Ensure the WASM module has sufficient heap (avoid large simultaneous buffers; free with closeDocAndFreeBuffer promptly).","Rate-limit bulk annotation creation and verify each annotation pointer before continuing.","On failure, abort the transaction rather than continuing with a partial set of annotations.","Re-open the document and retry once; if it persists, report the page as uneditable."],"exampleFix":"// before\nconst annotPtr = m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK);\nif (!annotPtr) throw new Error(\"Failed to create link annotation\");\n\n// after\nconst annotPtr = m.FPDFPage_CreateAnnot(pagePtr, FPDF_ANNOT_LINK);\nif (!annotPtr) {\n  throw new Error(\n    \"Failed to create link annotation: PDFium could not allocate the annotation (possible WASM memory exhaustion or corrupt page).\",\n  );\n}","handlingStrategy":"retry","validationCode":"// No pure pre-check exists for PDFium annotation allocation; budget the heap instead.\n// Ensure prior buffers are freed and keep a single open document at a time.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Free WASM buffers (closeDocAndFreeBuffer) promptly between operations.","Rate-limit bulk annotation creation and verify each annotation pointer.","Abort the transaction on first failure rather than producing a partial set."],"tags":["pdfium","wasm","memory","annotation"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}