{"record":{"id":"f2970c1d1974779e","repo":"Stirling-Tools/Stirling-PDF","slug":"pdfium-failed-to-create-destination-document","errorCode":null,"errorMessage":"PDFium: failed to create destination document","messagePattern":"PDFium: failed to create destination document","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"frontend/editor/src/core/services/pdfExportService.ts","lineNumber":118,"sourceCode":"        `Failed to export PDF: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n        { cause: error },\n      );\n    }\n  }\n\n  /**\n   * Create a PDF document from multiple source files using PDFium WASM.\n   */\n  private async createMultiSourceDocument(\n    sourceFiles: Map<string, File>,\n    pages: PDFPage[],\n  ): Promise<Blob> {\n    const m = await getPdfiumModule();\n\n    // Create destination document\n    const destDocPtr = m.FPDF_CreateNewDocument();\n    if (!destDocPtr)\n      throw new Error(\"PDFium: failed to create destination document\");\n\n    // Load all source documents once and cache them\n    const loadedDocs = new Map<string, number>();\n\n    try {\n      for (const [fileId, file] of sourceFiles) {\n        try {\n          const arrayBuffer = await file.arrayBuffer();\n          const docPtr = await openRawDocumentSafe(arrayBuffer);\n          loadedDocs.set(fileId, docPtr);\n        } catch (error) {\n          console.warn(`Failed to load source file ${fileId}:`, error);\n        }\n      }\n\n      let insertIdx = 0;\n      for (const page of pages) {\n        if (page.isBlankPage || page.originalPageNumber === -1) {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/services/pdfExportService.ts#L100-L136","documentation":"`createMultiSourceDocument` calls `FPDF_CreateNewDocument()` (PDFium's allocator for a fresh empty PDF) and checks for a null pointer. PDFium returns 0 only when it cannot allocate the document object — overwhelmingly a sign of WASM heap exhaustion or the module being in a broken state, since an empty document is otherwise always creatable.","triggerScenarios":"Exporting after loading many large source files into PDFium (the WASM heap fills up); the PDFium module was partially corrupted by a prior bad pointer operation; an earlier `resetPdfiumModule()` left state inconsistent. Note: unlike `createSingleDocument`, the source doc pointer is not yet opened here, so nothing is leaked on this throw.","commonSituations":"Merging several large PDFs that already consumed the WASM 32-bit address space (max ~2-4GB); long-lived sessions where PDFium leaked document handles; Safari's tighter WASM memory limits.","solutions":["Call `resetPdfiumModule()` once and retry — this clears `_docDataPtrs` and rebuilds a fresh WASM instance.","Ensure every opened source doc is closed via `closeRawDocument`/`closeDocAndFreeBuffer` so the heap doesn't accumulate; audit for missing close paths.","Limit concurrent open PDFium documents; process sequentially and close before opening the next.","If reproducible, reduce the working set (export fewer files at once) or move heavy merging server-side."],"exampleFix":"// before\nconst destDocPtr = m.FPDF_CreateNewDocument();\nif (!destDocPtr) throw new Error(\"PDFium: failed to create destination document\");\n\n// after (retry once after resetting the module)\nlet destDocPtr = m.FPDF_CreateNewDocument();\nif (!destDocPtr) {\n  resetPdfiumModule();\n  const m2 = await getPdfiumModule();\n  destDocPtr = m2.FPDF_CreateNewDocument();\n  if (!destDocPtr) throw new Error(\"PDFium: failed to create destination document\");\n}","handlingStrategy":"retry","validationCode":"// Heuristic: bound simultaneous open PDFium documents before merging\nconst MAX_OPEN_DOCS = 8;\nif (sourceFiles.size > MAX_OPEN_DOCS) {\n  console.warn(`Merging ${sourceFiles.size} files; consider sequential close to avoid WASM heap exhaustion.`);\n}","typeGuard":null,"tryCatchPattern":"async function withModuleRetry<T>(fn: () => Promise<T>): Promise<T> {\n  try { return await fn(); }\n  catch (e) {\n    if (e instanceof Error && e.message.includes(\"failed to create destination document\")) {\n      resetPdfiumModule();\n      return await fn();\n    }\n    throw e;\n  }\n}","preventionTips":["Close every opened source doc via `closeRawDocument` as soon as its pages are imported.","Process source files sequentially, not all-open-at-once, to cap WASM heap growth.","Retry once after `resetPdfiumModule()` on allocation failures.","Track live document-handle counts and warn the user near limits."],"tags":["pdfium","wasm","memory","export","multi-file"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}