docusealco/docuseal · error · Pdfium::PdfiumError

Failed to load document from memory, pointer is NULL.

Error message

Failed to load document from memory, pointer is NULL.

What it means

Raised by Pdfium::Document.open_bytes when FPDF_LoadMemDocument returns NULL for the in-memory buffer copied into an FFI::MemoryPointer via bytes.bytesize/put_bytes. check_last_error runs first and raises the richer error-code variant (PasswordError for FPDF_ERR_PASSWORD) when PDFium recorded a code, so this plain message typically means empty or truncated bytes, or data that is not a PDF. A non-String argument fails earlier with NoMethodError on bytesize.

Source

Thrown at lib/pdfium.rb:629

      return doc unless block_given?

      begin
        yield doc
      ensure
        doc.close
      end
    end

    def self.open_bytes(bytes, password = nil)
      buffer = FFI::MemoryPointer.new(:char, bytes.bytesize)
      buffer.put_bytes(0, bytes)

      doc_ptr = Pdfium.FPDF_LoadMemDocument(buffer, bytes.bytesize, password)

      if doc_ptr.null?
        Pdfium.check_last_error('Failed to load document from memory')

        raise PdfiumError, 'Failed to load document from memory, pointer is NULL.'
      end

      doc = new(doc_ptr, buffer)

      return doc unless block_given?

      begin
        yield doc
      ensure
        doc.close
      end
    end

    def self.open_io(io, password = nil, &)
      path = io.path if io.respond_to?(:path)

      if path
        io.flush

View on GitHub (pinned to 004a22c1c8)

Solutions

  1. Guard for empty input and verify bytes.start_with?('%PDF') before loading
  2. Force binary encoding on the string: bytes.force_encoding(Encoding::BINARY) before open_bytes
  3. If the source is a file or IO, prefer open_file/open_io which handle encoding and streaming
  4. Rescue Pdfium::PasswordError and retry with the password for encrypted documents

Example fix

# before
doc = Pdfium::Document.open_bytes(data)

# after
raise ArgumentError, 'not a PDF' unless data.is_a?(String) && data.bytesize.positive? && data.start_with?('%PDF')

doc = Pdfium::Document.open_bytes(data.b)
Defensive patterns

Strategy: validation

Validate before calling

def loadable_pdf_bytes?(bytes)
  bytes.is_a?(String) && bytes.bytesize.positive? && bytes.start_with?('%PDF')
end

raise ArgumentError, 'not a PDF' unless loadable_pdf_bytes?(bytes)
bytes = bytes.b

Try / catch

begin
  Pdfium::Document.open_bytes(bytes, password)
rescue Pdfium::PasswordError
  retry_with_password
rescue Pdfium::PdfiumError => e
  reject_payload(e.message)
end

Prevention

When it happens

Trigger: Passing '' or header-only bytes from a truncated download; passing base64 text that was never decoded; a String read from an IO without binmode; an encrypted document with a missing password (raises the PasswordError variant instead).

Common situations: Handling multipart uploads or object-storage GETs that returned partial content; decoding email attachments; test fixtures with wrong encodings; passing already-decoded JSON fields.

Related errors


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