{"record":{"id":"28841b25dbe6ed4e","repo":"docusealco/docuseal","slug":"failed-to-load-text-page","errorCode":null,"errorMessage":"Failed to load text page","messagePattern":"Failed to load text page","errorType":"exception","errorClass":"Pdfium::PdfiumError","httpStatus":null,"severity":"error","filePath":"lib/pdfium.rb","lineNumber":1216,"sourceCode":"          content = buffer.read_bytes(written - 2).force_encoding('UTF-16LE').encode('UTF-8')\n\n          blanks << object_ptr if content.codepoints.all? { |code| BLANK_TEXT_CODEPOINTS.include?(code) }\n        end\n      ensure\n        Pdfium.FPDFText_ClosePage(text_page)\n      end\n\n      return if blanks.empty?\n\n      blanks.each { |object_ptr| remove_page_object(object_ptr) }\n\n      Pdfium.FPDFPage_GenerateContent(@page_ptr)\n    end\n\n    def remove_redacted_chars(rect_bounds)\n      text_page = Pdfium.FPDFText_LoadPage(@page_ptr)\n\n      raise PdfiumError, 'Failed to load text page' if text_page.null?\n\n      begin\n        text_objects_chars = collect_text_objects_chars(text_page, rect_bounds)\n      ensure\n        Pdfium.FPDFText_ClosePage(text_page)\n      end\n\n      text_objects_chars.each_value do |entry|\n        next if entry[:chars].none? { |char| char[:redacted] }\n\n        rebuild_text_object_survivors(entry) unless entry[:chars].all? { |char| char[:redacted] }\n\n        remove_page_object(entry[:ptr])\n      end\n    end\n\n    def unwrap_form_objects(rect_bounds = nil)\n      unwrapped = false","sourceCodeStart":1198,"sourceCodeEnd":1234,"githubUrl":"https://github.com/docusealco/docuseal/blob/004a22c1c88109c7ba0b567df011a8cb13894001/lib/pdfium.rb#L1198-L1234","documentation":"Raised inside Page#redact via remove_redacted_chars when FPDFText_LoadPage returns NULL for the page being redacted. Unlike the Page#text variant there is no check_last_error and no page index in the message. unwrap_form_objects has already run when this fires, so the page is partially modified; re-open the document before any save rather than persisting the half-edited state.","triggerScenarios":"Calling redact on a page with an unparseable text layer or corrupt content stream; redacting a page whose form unwrapping left its content stream inconsistent.","commonSituations":"Bulk redaction over heterogeneous user uploads where a few files are damaged; redacting previously-redacted documents.","solutions":["Pre-screen with page.text (rescuable) and skip redaction for pages that cannot build a text page","Re-open the original and retry once","Repair the PDF (qpdf or ghostscript) before redaction","For scan-only pages, use a draw-only fallback that paints opaque rects without character surgery"],"exampleFix":"# before\npage.redact(rects)\n\n# after - skip pages whose text layer cannot even load\nbegin\n  page.text # pre-screen: same underlying FPDFText_LoadPage\nrescue Pdfium::PdfiumError\n  next # or draw-only fallback\nend\npage.redact(rects)","handlingStrategy":"fallback","validationCode":"begin\n  page.text # same FPDFText_LoadPage call the redact path uses\nrescue Pdfium::PdfiumError\n  return skip_or_flag_page(page)\nend\npage.redact(rects)","typeGuard":null,"tryCatchPattern":"begin\n  page.redact(rects)\nrescue Pdfium::PdfiumError => e\n  raise unless e.message == 'Failed to load text page'\n  page_redact_draw_only(page, rects) # opaque rects, no char surgery\nend","preventionTips":["Pre-screen damaged pages with page.text before redacting them","Repair uploads (qpdf/ghostscript) in the ingestion stage","Retry redactions from the original bytes, never from a half-redacted document"],"tags":["pdfium","redaction","text-extraction","corrupt-pdf","ruby"],"backgroundTag":"pdf-text-extraction-failed","analyzedSha":"004a22c1c88109c7ba0b567df011a8cb13894001","analyzedAt":"2026-08-21T13:38:23.343Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}