{"record":{"id":"2a75c7cf1f70539c","repo":"docusealco/docuseal","slug":"failed-to-load-page-page-index-pointer-is-null","errorCode":null,"errorMessage":"Failed to load page #{page_index}, pointer is NULL.","messagePattern":"Failed to load page #(.+?), pointer is NULL\\.","errorType":"exception","errorClass":"Pdfium::PdfiumError","httpStatus":null,"severity":"error","filePath":"lib/pdfium.rb","lineNumber":931,"sourceCode":"  end\n\n  class Page\n    attr_reader :document, :page_index, :page_ptr\n\n    def initialize(document, page_index)\n      raise ArgumentError, 'Document object is required' unless document.is_a?(Pdfium::Document)\n\n      @document = document\n      @document.ensure_not_closed!\n\n      @page_index = page_index\n\n      @page_ptr = Pdfium.FPDF_LoadPage(document.document_ptr, page_index)\n\n      if @page_ptr.null?\n        Pdfium.check_last_error(\"Failed to load page #{page_index}\")\n\n        raise PdfiumError, \"Failed to load page #{page_index}, pointer is NULL.\"\n      end\n\n      @closed = false\n    end\n\n    def width\n      @width ||= Pdfium.FPDF_GetPageWidthF(@page_ptr)\n    end\n\n    def height\n      @height ||= Pdfium.FPDF_GetPageHeightF(@page_ptr)\n    end\n\n    def annotations\n      ensure_not_closed!\n\n      @annotations ||=\n        (0...Pdfium.FPDFPage_GetAnnotCount(page_ptr)).filter_map do |index|","sourceCodeStart":913,"sourceCodeEnd":949,"githubUrl":"https://github.com/docusealco/docuseal/blob/004a22c1c88109c7ba0b567df011a8cb13894001/lib/pdfium.rb#L913-L949","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use doc.get_page(index) instead of Pdfium::Page.new - it validates the range and memoizes pages","Verify the document opens cleanly and page_count exceeds the index before page work","Repair the PDF externally (qpdf --decrypt, ghostscript) and retry","Never share a Document across threads; open one per thread"],"exampleFix":"# before\npage = Pdfium::Page.new(doc, 4)\n\n# after\npage = doc.get_page(4)","handlingStrategy":"validation","validationCode":"page = doc.get_page(idx) # get_page validates range and memoizes; prefer over Page.new\nraise ArgumentError, 'page unavailable' if idx >= doc.page_count","typeGuard":null,"tryCatchPattern":"begin\n  page = doc.get_page(idx)\nrescue Pdfium::PdfiumError => e\n  raise unless e.message.include?('pointer is NULL')\n  nil # skip unloadable page of a damaged document\nend","preventionTips":["Never construct Pdfium::Page directly; Document#get_page is the supported entry point","Keep one Document per thread; pdfium handles are not thread-safe","Pre-repair damaged uploads (qpdf --decrypt) in ingestion pipelines"],"tags":["pdfium","page-loading","corrupt-pdf","ffi","ruby"],"backgroundTag":"pdf-page-load-failed","analyzedSha":"004a22c1c88109c7ba0b567df011a8cb13894001","analyzedAt":"2026-08-21T13:38:23.343Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}