docusealco/docuseal · error · Pdfium::PdfiumError

Failed to load page #{page_index}, pointer is NULL.

Error message

Failed to load page #{page_index}, pointer is NULL.

What it means

Raised by Page#initialize when FPDF_LoadPage returns NULL for the requested page index. check_last_error runs first and raises the error-code variant if PDFium recorded one, so this plain message means a NULL page handle with no recorded code, usually a page tree damaged enough that a counted page cannot load. Document#get_page range-checks before constructing Page, so this mainly fires when Pdfium::Page.new is called directly, or when the document is damaged or being closed concurrently.

Source

Thrown at lib/pdfium.rb:931

  end

  class Page
    attr_reader :document, :page_index, :page_ptr

    def initialize(document, page_index)
      raise ArgumentError, 'Document object is required' unless document.is_a?(Pdfium::Document)

      @document = document
      @document.ensure_not_closed!

      @page_index = page_index

      @page_ptr = Pdfium.FPDF_LoadPage(document.document_ptr, page_index)

      if @page_ptr.null?
        Pdfium.check_last_error("Failed to load page #{page_index}")

        raise PdfiumError, "Failed to load page #{page_index}, pointer is NULL."
      end

      @closed = false
    end

    def width
      @width ||= Pdfium.FPDF_GetPageWidthF(@page_ptr)
    end

    def height
      @height ||= Pdfium.FPDF_GetPageHeightF(@page_ptr)
    end

    def annotations
      ensure_not_closed!

      @annotations ||=
        (0...Pdfium.FPDFPage_GetAnnotCount(page_ptr)).filter_map do |index|

View on GitHub (pinned to 004a22c1c8)

Solutions

  1. Use doc.get_page(index) instead of Pdfium::Page.new - it validates the range and memoizes pages
  2. Verify the document opens cleanly and page_count exceeds the index before page work
  3. Repair the PDF externally (qpdf --decrypt, ghostscript) and retry
  4. Never share a Document across threads; open one per thread

Example fix

# before
page = Pdfium::Page.new(doc, 4)

# after
page = doc.get_page(4)
Defensive patterns

Strategy: validation

Validate before calling

page = doc.get_page(idx) # get_page validates range and memoizes; prefer over Page.new
raise ArgumentError, 'page unavailable' if idx >= doc.page_count

Try / catch

begin
  page = doc.get_page(idx)
rescue Pdfium::PdfiumError => e
  raise unless e.message.include?('pointer is NULL')
  nil # skip unloadable page of a damaged document
end

Prevention

When it happens

Trigger: Calling Pdfium::Page.new(doc, 5) with a plausible index on a corrupt PDF whose page tree is broken; a page whose object another thread removed; constructing a page while the owning document is being closed.

Common situations: Malformed PDFs that pdfium repaired at load (page_count reflects the xref, not loadable pages); concurrent access to a shared Document from multiple threads, which pdfium handles do not support.

Related errors


AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21). Data as JSON: /api/errors/2a75c7cf1f70539c. Report an issue: GitHub.