Bug Report for Upstream pypdf Project
Purpose: This issue tracks the need to report and fix a bug in the pypdf library (py-pdf/pypdf).
Summary
pypdf crashes with AttributeError: 'dict' object has no attribute 'get_object' when filling form fields in PDFs that lack a /DR (Default Resources) entry in the AcroForm dictionary and reference fonts not in CORE_FONT_METRICS.
Location
- File:
pypdf/generic/_appearance_stream.py
- Line: 437
- Function:
TextStreamAppearance.from_text_annotation()
- Version: pypdf 5.7.0+ (tested with 6.3.0+)
Root Cause
Lines 433-437 contain a type error:
# BUGGY CODE
document_resources = cast(
dict[Any, Any],
acro_form.get("/DR", {}), # ← Returns plain dict {} if /DR missing
)
document_font_resources = document_resources.get_object().get("/Font", DictionaryObject()).get_object()
The Problem:
cast() is only a type hint - it doesn't convert the object
acro_form.get("/DR", {}) returns:
- A pypdf
DictionaryObject if /DR exists (has .get_object() method)
- A plain Python
dict {} if /DR is missing (no .get_object() method)
- Line 437 unconditionally calls
.get_object(), which crashes when the default {} is returned
Correct Pattern
The same file already shows the correct pattern on lines 419-428:
# CORRECT CODE (lines 419-428)
document_resources = cast(
DictionaryObject,
cast(
DictionaryObject,
acro_form.get("/DR", DictionaryObject()), # ← Uses DictionaryObject() as default
).get_object(), # ← Calls get_object() immediately
)
Proposed Fix
Replace lines 433-437 with:
document_resources = cast(
DictionaryObject,
cast(
DictionaryObject,
acro_form.get("/DR", DictionaryObject()), # ← Change {} to DictionaryObject()
).get_object(),
)
document_font_resources = document_resources.get("/Font", DictionaryObject()).get_object()
Minimal Complete Verifiable Example (MCVE)
Reproduction Code
from pypdf import PdfReader, PdfWriter
# Create a PDF with form fields using PyMuPDF
import fitz
doc = fitz.new()
page = doc.new_page(width=612, height=792)
# Add a text field with /Helv font (not in CORE_FONT_METRICS)
widget = fitz.Widget()
widget.field_type = fitz.PDF_WIDGET_TYPE_TEXT
widget.field_name = "test_field"
widget.rect = fitz.Rect(50, 50, 300, 70)
widget.text_fontsize = 10
widget.text_font = "helv" # This becomes /Helv in default appearance
widget.fill_color = (1, 1, 1)
widget.border_color = (0.7, 0.7, 0.7)
page.add_widget(widget)
doc.save("test_form.pdf")
doc.close()
# Now try to fill the field with pypdf
reader = PdfReader("test_form.pdf")
writer = PdfWriter(clone_from=reader)
# This will crash with AttributeError
writer.update_page_form_field_values(
writer.pages[0],
{"test_field": "Test Value"},
auto_regenerate=False
)
writer.set_need_appearances_writer(True)
with open("test_form_filled.pdf", "wb") as f:
writer.write(f)
Error Output
Traceback (most recent call last):
File "test.py", line 29, in <module>
writer.update_page_form_field_values(
File "/path/to/pypdf/_writer.py", line 1045, in update_page_form_field_values
appearance_stream_obj = TextStreamAppearance.from_text_annotation(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/path/to/pypdf/generic/_appearance_stream.py", line 437, in from_text_annotation
document_font_resources = document_resources.get_object().get("/Font", DictionaryObject()).get_object()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'get_object'
PDF Characteristics
The bug occurs when:
- AcroForm dictionary has no
/DR (Default Resources) entry
- Form field default appearance references a font not in CORE_FONT_METRICS (e.g.,
/Helv)
- Code reaches the fallback path at lines 431-437
CORE_FONT_METRICS includes: Helvetica, Courier, Times-Roman, Arial, etc. (but NOT "Helv")
Workaround
Until fixed, use fonts that are in CORE_FONT_METRICS:
- Change
/Helv to /Helvetica in PDF default appearance strings
- Or add a
/DR dictionary to the AcroForm with proper font resources
Testing Strategy
A proper unit test should:
- Create a PDF with form fields lacking
/DR in AcroForm
- Use a font reference not in CORE_FONT_METRICS (e.g.,
/Helv)
- Attempt to update field values using
update_page_form_field_values()
- Verify it either succeeds or fails gracefully (not with AttributeError)
Labels for pypdf Issue
When reporting to pypdf, use labels:
is-bug
workflow-forms
needs-pdf (will attach sample PDF)
Action Items
Bug Report for Upstream pypdf Project
Purpose: This issue tracks the need to report and fix a bug in the pypdf library (py-pdf/pypdf).
Summary
pypdf crashes with
AttributeError: 'dict' object has no attribute 'get_object'when filling form fields in PDFs that lack a/DR(Default Resources) entry in the AcroForm dictionary and reference fonts not in CORE_FONT_METRICS.Location
pypdf/generic/_appearance_stream.pyTextStreamAppearance.from_text_annotation()Root Cause
Lines 433-437 contain a type error:
The Problem:
cast()is only a type hint - it doesn't convert the objectacro_form.get("/DR", {})returns:DictionaryObjectif/DRexists (has.get_object()method)dict{}if/DRis missing (no.get_object()method).get_object(), which crashes when the default{}is returnedCorrect Pattern
The same file already shows the correct pattern on lines 419-428:
Proposed Fix
Replace lines 433-437 with:
Minimal Complete Verifiable Example (MCVE)
Reproduction Code
Error Output
PDF Characteristics
The bug occurs when:
/DR(Default Resources) entry/Helv)CORE_FONT_METRICS includes: Helvetica, Courier, Times-Roman, Arial, etc. (but NOT "Helv")
Workaround
Until fixed, use fonts that are in CORE_FONT_METRICS:
/Helvto/Helveticain PDF default appearance strings/DRdictionary to the AcroForm with proper font resourcesTesting Strategy
A proper unit test should:
/DRin AcroForm/Helv)update_page_form_field_values()Labels for pypdf Issue
When reporting to pypdf, use labels:
is-bugworkflow-formsneeds-pdf(will attach sample PDF)Action Items