docusealco/docuseal · error · Pdfium::PdfiumError

Document is closed.

Error message

Document is closed.

What it means

Guard raised by Document#ensure_not_closed! when any operation is attempted on a document after close. close nulls the document handle, closes every cached page, exits the form-fill environment and frees buffers, so later use would be a use-after-free at the FFI boundary; this guard converts that into a Ruby exception. The block forms of Document.create/open_file/open_bytes/open_io close the document in an ensure clause, so using the doc outside the block is the most common trigger.

Solutions

  1. Perform all work inside the open block, or use the non-block form and call doc.close yourself in an ensure
  2. Check doc.closed? before reuse and re-open the document when true
  3. Return extracted data (strings, arrays, rendered bytes) rather than Document/Page objects from the scope that owns their lifecycle

Example fix

# before
doc = nil
Pdfium::Document.open_file(path) { |d| doc = d }
doc.page_count # raises Document is closed.

# after
Pdfium::Document.open_file(path) do |doc|
  @count = doc.page_count
end
Defensive patterns

Strategy: validation

Validate before calling

if doc.closed?
  doc = Pdfium::Document.open_file(path) # or raise/re-open from source bytes
end

Try / catch

begin
  doc.get_page(0)
rescue Pdfium::PdfiumError => e
  raise unless e.message == 'Document is closed.'
  reopen_and_retry
end

Prevention

When it happens

Trigger: Capturing the yielded doc from Pdfium::Document.open_file(path) { |d| } and calling methods on it after the block; saving a document after its open block returned; storing the doc in an instance variable and touching it in a later request or job.

Common situations: Rails controllers that open with the block form but stash the doc for the view; background jobs returning Document objects instead of extracted data; retry code that reuses a doc already closed by ensure.

Related errors


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

Appendix: source

Thrown at lib/pdfium.rb:693

      end

      doc = new(doc_ptr, [file_access, get_block, io])

      return doc unless block_given?

      begin
        yield doc
      ensure
        doc.close
      end
    end

    def closed?
      @closed
    end

    def ensure_not_closed!
      raise PdfiumError, 'Document is closed.' if closed?
    end

    def get_page(page_index)
      ensure_not_closed!

      unless page_index.is_a?(Integer) && page_index >= 0 && page_index < page_count
        raise PdfiumError, "Page index #{page_index} out of range (0..#{page_count - 1})"
      end

      @pages[page_index] ||= Page.new(self, page_index)
    end

    def bookmarks(parent = nil, seen = Set.new)
      acc = []
      bookmark = Pdfium.FPDFBookmark_GetFirstChild(@document_ptr, parent)

      until bookmark.null?
        break unless seen.add?(bookmark.address)

View on GitHub (pinned to 004a22c1c8)