docusealco/docuseal · error · Pdfium::PdfiumError
Failed to import pages
Error message
Failed to import pages
What it means
Pdfium::Document#import_pages wraps FPDF_ImportPages from the PDFium C API and raises PdfiumError 'Failed to import pages' when the native call returns 0. Failure means the requested pages could not be inserted into the destination document: an invalid page specification string, an out-of-range page number, a source document that is closed or cannot yield pages (corrupt or extraction-restricted), or FFI marshalling problems after a pdfium upgrade. The subsequent FPDF_ImportAcroForm call only runs on success.
Source
Thrown at lib/pdfium.rb:571
def page_count
@page_count ||= Pdfium.FPDF_GetPageCount(@document_ptr)
end
def encrypted?
Pdfium.FPDF_GetSecurityHandlerRevision(@document_ptr) >= 0
end
def form?
Pdfium.FPDF_GetFormType(@document_ptr) != Pdfium::FORMTYPE_NONE
end
def import_pages(src_doc, pages: nil, index: nil)
ensure_not_closed!
result = Pdfium.FPDF_ImportPages(@document_ptr, src_doc.document_ptr, pages, index || page_count)
raise PdfiumError, 'Failed to import pages' if result.zero?
Pdfium.FPDF_ImportAcroForm(@document_ptr, src_doc.document_ptr)
@page_count = nil
result
end
def self.create
doc_ptr = Pdfium.FPDF_CreateNewDocument()
if doc_ptr.null?
Pdfium.check_last_error('Failed to create new document')
raise PdfiumError, 'Failed to create new document'
end
doc = new(doc_ptr)View on GitHub (pinned to 004a22c1c8)
Solutions
- Log the pages argument, both documents' page_count, and encryption status right before the call, and validate the 1-based range.
- Ensure both documents are open and readable - import from a freshly opened source when in doubt.
- Reproduce outside the app with qpdf or pdfium tooling on the same file pair to confirm the documents themselves merge.
- Repair/normalize inputs first (e.g. qpdf --decrypt or a re-save) and retry.
- After pdfium upgrades, verify the FPDF_ImportPages signature and string marshalling in the FFI layer.
Example fix
# before
result = doc.import_pages(src_doc, pages: params[:pages])
# after
pages = params[:pages].to_s
if pages.present?
nums = pages.scan(/\d+/).map(&:to_i)
raise ArgumentError, 'page out of range' if nums.any? { |n| n < 1 || n > src_doc.page_count }
end
result = doc.import_pages(src_doc, pages: pages.presence) Defensive patterns
Strategy: validation
Validate before calling
pages = params[:pages].to_s
if pages.present?
nums = pages.scan(/\d+/).map(&:to_i)
raise ArgumentError, 'page out of range' if nums.any? { |n| n < 1 || n > src_doc.page_count }
end
doc.import_pages(src_doc, pages: pages.presence) Try / catch
begin
doc.import_pages(src_doc, pages: pages)
rescue Pdfium::PdfiumError => e
mark_merge_failed(document_id)
Rails.logger.error("import_pages failed: #{e.message} pages=#{pages}")
end Prevention
- Validate page ranges at the API boundary
- Normalize or repair uploaded PDFs before merging
- Keep the pdfium binary and FFI bindings version-locked
When it happens
Trigger: Passing a pages string like '0', or '5' for a 3-page source, or a malformed range; src_doc already closed (only the destination's ensure_not_closed! is checked here); merging secured or encrypted PDFs that forbid extraction; pdfium library version drift changing argument expectations.
Common situations: Template merge features with user-supplied page ranges; password-protected or permissions-locked PDF uploads; upgrading the pdfium binary without re-checking bindings; corrupted uploads that open but fail deep operations.
Related errors
- Failed to load redacted image
- Failed to flatten page #{page_index}
- Failed to reload page #{page_index}
- Failed to create new document
- Failed to load document from file '#{file_path}', pointer is
AI-assisted analysis of docusealco/docuseal@004a22c1c8 (2026-08-21).
Data as JSON: /api/errors/e5aceb66be84132b.
Report an issue: GitHub.