Repository navigation
Every conversion fails with PydanticSerializationError: Circular reference detected (pipeline_cache regression) #4229
Description
Bug
Every conversion fails immediately, before any document I/O happens, with:
pydantic_core._pydantic_core.PydanticSerializationError: Error serializing to JSON:
PydanticSerializationError: Error calling function `<lambda>`: ValueError: Circular reference detected (id repeated)
This isn't specific to any input file, URL, or pipeline options. It reproduces with a bare default PdfPipelineOptions():
from docling.datamodel.pipeline_options import PdfPipelineOptions
opts = PdfPipelineOptions()
opts.model_dump_json(serialize_as_any=True) # raises PydanticSerializationErrorBisected this to #4076 ("fix: avoid pipeline option cache key collisions"), which added docling/utils/pipeline_cache.py::create_pipeline_options_hash. That function calls pipeline_options.model_dump_json(serialize_as_any=True) to build a cache key, and document_converter.py::_get_pipeline calls it on every conversion. With serialize_as_any=True, pydantic-core's cycle guard false-positives on shared singleton objects reachable from multiple branches of the default option tree. There's no actual cycle.
The regression spans v2.123.1 (first release containing #4076) through the current latest, v2.126.0. Downgrading to v2.122.0 avoids it. model_dump_json(serialize_as_any=True) succeeds there on the same default options object.
Steps to reproduce
pip install docling==2.126.0docling https://arxiv.org/pdf/2206.01062 --output ./out(or convert any local file, e.g. a plain.txt)- Observe the traceback below, raised from
_get_pipeline→create_pipeline_options_hash→model_dump_json(serialize_as_any=True), before any document is read or fetched.
Minimal repro without the CLI:
from docling.datamodel.pipeline_options import PdfPipelineOptions
PdfPipelineOptions().model_dump_json(serialize_as_any=True)Full traceback:
Traceback (most recent call last):
File "/opt/homebrew/bin/docling", line 6, in <module>
sys.exit(app())
File ".../docling/cli/main.py", line 1667, in convert
export_documents(
File ".../docling/cli/main.py", line 500, in export_documents
for conv_res in conv_results:
File ".../docling/document_converter.py", line 635, in convert_all
for conv_res in conv_res_iter:
File ".../docling/document_converter.py", line 764, in _convert
for item in map(
File ".../docling/document_converter.py", line 811, in _process_document
conv_res = self._execute_pipeline(in_doc, raises_on_error=raises_on_error)
File ".../docling/document_converter.py", line 837, in _execute_pipeline
pipeline = self._get_pipeline(in_doc.format)
File ".../docling/document_converter.py", line 784, in _get_pipeline
options_hash = create_pipeline_options_hash(pipeline_options)
File ".../docling/utils/pipeline_cache.py", line 22, in create_pipeline_options_hash
payload = type(pipeline_options).__qualname__ + pipeline_options.model_dump_json(
File ".../pydantic/main.py", line 519, in model_dump_json
return self.__pydantic_serializer__.to_json(
pydantic_core._pydantic_core.PydanticSerializationError: Error serializing to JSON: PydanticSerializationError: Error calling function `<lambda>`: ValueError: Circular reference detected (id repeated)
Docling version
Docling version: 2.126.0
Docling Core version: 2.96.0
Docling IBM Models version: 4.0.2
Docling Parse version: 7.19.1
Python: cpython-311 (3.11.16)
Platform: macOS-26.6.2-arm64-arm-64bit
pydantic 2.11.9, pydantic_core 2.33.2
Python version
Python 3.11.16
Activity
teachershuang commentedon Sep 12, 2026
I reproduced the default
PdfPipelineOptionscache-hash failure on Windows / Python 3.12.13 with Pydantic 2.11.9 (core 2.33.2). The same call succeeds with 2.12.0 and the locked 2.13.5. I used isolated version overlays; the cache/options source is identical to current main 5ea6490. This is a cache-entry-point reproduction, not a full conversion/version-matrix validation.The declared requirement still allows
pydantic>=2.0.0,<3.0.0. I checked #4076 and would preserve its runtime-subtype cache-key distinctions: simply removingserialize_as_any=Truerisks restoring the collisions that PR fixed, and its maintainer revision intentionally avoided a full type walker.I would be happy to take a narrow compatibility fix. Before implementing, do maintainers want to retain support for the older Pydantic versions here, or is raising the minimum to a verified working version acceptable? 2.12.0 passing this reproduction does not establish the earliest fixed version or full compatibility.
After direction is agreed, I would cover the default-options failure, the existing subtype/collision regressions, and converter/extractor cache entry points across the agreed supported versions. No serialization redesign, dependency change or implementation PR yet. Investigation and follow-up implementation are AI-assisted.
fix(cache): fall back safely when serialize_as_any detects false circ…
fix(cache): fall back safely when serialize_as_any detects false circ…
fix(cache): fall back safely when serialize_as_any detects false circ…