Stirling-Tools/Stirling-PDF · error · Error

Failed to build payload

Error message

Failed to build payload

What it means

Thrown when buildPayload() returns null during the fallback full-export path of the PDF text editor's save-to-workbench flow. buildPayload() returns null only when loadedDocument is falsy (PdfTextEditor.tsx:1214). This error fires after an incremental/partial export already failed (caught in the catch block), meaning the component tried to recover via a full rebuild but had no loaded document to rebuild from.

Source

Thrown at frontend/editor/src/core/tools/pdfTextEditor/PdfTextEditor.tsx:1591

              },
            );
          }
          console.warn(
            "[handleSaveToWorkbench] Incremental export failed, falling back to full export",
            incrementalError,
          );
          // Fall through to full export
          if (isLazyMode && totalPages > 0) {
            const allPageIndices = Array.from(
              { length: totalPages },
              (_, index) => index,
            );
            await ensureImagesForPages(allPageIndices);
          }

          const payload = buildPayload();
          if (!payload) {
            throw new Error("Failed to build payload", {
              cause: incrementalError,
            });
          }

          const { document, filename } = payload;
          const serialized = JSON.stringify(document);
          const jsonFile = new File([serialized], filename, {
            type: "application/json",
          });

          const formData = new FormData();
          formData.append("fileInput", jsonFile);
          const response = await apiClient.post(
            CONVERSION_ENDPOINTS["text-editor-pdf"],
            formData,
            {
              responseType: "blob",
            },

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Guard against loadedDocument being null before entering the export flow; bail early with a user-facing message instead of reaching the fallback.
  2. Capture the document snapshot synchronously before the first await (incremental export) so the fallback still has data.
  3. Verify cachedJobId validity before the incremental call to avoid the initial failure that triggers the fallback.
  4. If the document is genuinely gone, show a toast prompting the user to reload the PDF rather than throwing.

Example fix

// before
const payload = buildPayload();
if (!payload) {
  throw new Error("Failed to build payload", { cause: incrementalError });
}

// after
const payload = buildPayload();
if (!payload) {
  alert({
    alertType: "error",
    title: t("pdfTextEditor.export.documentMissing", "The document is no longer loaded. Please reopen the file and try again."),
  });
  return;
}
Defensive patterns

Strategy: validation

Validate before calling

// Before entering the export fallback, snapshot the document synchronously:
const docSnapshot = loadedDocumentRef.current;
if (!docSnapshot) {
  alert({ alertType: "error", title: "Document no longer loaded. Please reopen the file." });
  return;
}
// pass docSnapshot into buildPayload so the fallback always has data

Type guard

// Narrow before use
function hasLoadedDocument(doc: unknown): doc is LoadedDocument {
  return !!doc && typeof doc === "object" && Array.isArray((doc as LoadedDocument).pages);
}

Try / catch

// In the catch block, validate payload presence gracefully:
} catch (incrementalError) {
  const payload = buildPayload();
  if (!payload) {
    console.error("Fallback export skipped: document not loaded", incrementalError);
    alert({ alertType: "error", title: "Export failed. Please reload the PDF and retry." });
    return;
  }
  // ... proceed with full export
}

Prevention

When it happens

Trigger: An incremental export via /api/v1/convert/pdf/text-editor/partial/{cachedJobId} threw (network error, 4xx/5xx, expired cachedJobId). The catch block then attempted a full export fallback, but loadedDocument was null/undefined at that moment — e.g. the document was unloaded or cleared while the async export was in flight, or the component was unmounted mid-save.

Common situations: User navigates away or closes the editor while a large lazy-mode PDF is exporting. Race condition where the editor's document state is reset (file context swap, memory cleanup) before the fallback export runs. The incremental export failed because the cached job expired (server eviction) and the editor state was concurrently cleared.

Related errors


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