Stirling-Tools/Stirling-PDF · error · Error

PDFium: failed to initialise form environment

Error message

PDFium: failed to initialise form environment

What it means

Thrown by PdfiumFormProvider.fillForm when PDFiumExt_InitFormFillEnvironment returns a null pointer: the WASM PDFium build could not create an AcroForm form-fill environment for the document.

Source

Thrown at frontend/editor/src/core/tools/formFill/providers/PdfiumFormProvider.ts:566

  }

  async fillForm(
    file: File | Blob,
    values: Record<string, string>,
    flatten: boolean,
  ): Promise<Blob> {
    const arrayBuffer = await file.arrayBuffer();
    const m = await getPdfiumModule();
    const docPtr = await openRawDocumentSafe(arrayBuffer);

    try {
      const formInfoPtr = m.PDFiumExt_OpenFormFillInfo();
      const formEnvPtr = m.PDFiumExt_InitFormFillEnvironment(
        docPtr,
        formInfoPtr,
      );
      if (!formEnvPtr) {
        throw new Error("PDFium: failed to initialise form environment");
      }

      const pageCount = m.FPDF_GetPageCount(docPtr);

      // Track radio widget index per field for index-based matching.
      // The UI stores radio values as widget indices (e.g., "0", "1", "2").
      const radioWidgetIdx = new Map<string, number>();

      for (let pageIdx = 0; pageIdx < pageCount; pageIdx++) {
        const pagePtr = m.FPDF_LoadPage(docPtr, pageIdx);
        if (!pagePtr) continue;
        m.FORM_OnAfterLoadPage(pagePtr, formEnvPtr);

        const annotCount = m.FPDFPage_GetAnnotCount(pagePtr);
        for (let ai = 0; ai < annotCount; ai++) {
          const annotPtr = m.FPDFPage_GetAnnot(pagePtr, ai);
          if (!annotPtr) continue;
          if (m.FPDFAnnot_GetSubtype(annotPtr) !== FPDF_ANNOT_WIDGET) {

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Detect encryption and XFA up front and reject or fall back to the pdf-lib provider.
  2. Validate the PDF header and encryption status before calling fillForm.
  3. Retry once with a fresh getPdfiumModule() instance for transient wasm state.
  4. Surface a user-facing message ('This form type is not supported') instead of a raw pointer error.

Example fix

// before
const formEnvPtr = m.PDFiumExt_InitFormFillEnvironment(docPtr, formInfoPtr);
if (!formEnvPtr) throw new Error('PDFium: failed to initialise form environment');

// after
const formEnvPtr = m.PDFiumExt_InitFormFillEnvironment(docPtr, formInfoPtr);
if (!formEnvPtr) {
  throw new FormUnsupportedError(
    'PDFium could not initialise this form (encrypted or XFA). Try decrypting or use a different form type.',
  );
}
Defensive patterns

Strategy: validation

Validate before calling

const encrypted = await isPdfEncrypted(file);
const xfa = await hasXfaForm(file);
if (encrypted || xfa) {
  throw new Error('Unsupported form: PDF is encrypted or XFA-only.');
}

Type guard

async function isPdfFormFillable(file: Blob): Promise<boolean> {
  if (await isPdfEncrypted(file)) return false;
  if (await hasXfaForm(file)) return false;
  return true;
}

Try / catch

try {
  return await pdfiumProvider.fillForm(file, values, flatten);
} catch (e) {
  if (e instanceof Error && /form environment/i.test(e.message)) {
    return await pdfLibProvider.fillForm(file, values, flatten); // fallback
  }
  throw e;
}

Prevention

When it happens

Trigger: The PDF is corrupted or encrypted (opened without credentials); it contains XFA-only (LiveCycle) forms that PDFium's AcroForm path cannot initialize; the AcroForm dictionary is malformed; or the WASM module is in a degraded state.

Common situations: User uploaded a password-encrypted PDF; an XFA dynamic form; a PDF from a generator with non-standard form dictionaries; rare WASM memory exhaustion during form init.

Related errors


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