Summary
The convert and chunk endpoints accept the same ConvertDocumentsRequestOptions object, but under different field names. Combined with Pydantic's default behavior of silently ignoring unknown fields, this causes user settings to be dropped without any error or warning.
Endpoints and their field names
Convert endpoints -- field: options
| Endpoint |
Request model |
Conversion options field |
POST /v1/convert/source |
ConvertDocumentsRequest |
options |
POST /v1/convert/source/async |
ConvertDocumentsRequest |
options |
{
"options": { "pipeline": "vlm", ... },
"sources": [...]
}
Chunk endpoints -- field: convert_options
| Endpoint |
Request model |
Conversion options field |
Chunking options field |
POST /v1/chunk/hybrid/source |
HybridChunkerOptionsDocumentsRequest |
convert_options |
chunking_options |
POST /v1/chunk/hybrid/source/async |
HybridChunkerOptionsDocumentsRequest |
convert_options |
chunking_options |
POST /v1/chunk/hierarchical/source |
HierarchicalChunkerOptionsDocumentsRequest |
convert_options |
chunking_options |
POST /v1/chunk/hierarchical/source/async |
HierarchicalChunkerOptionsDocumentsRequest |
convert_options |
chunking_options |
{
"convert_options": { "pipeline": "vlm", ... },
"chunking_options": { ... },
"sources": [...]
}
Both options and convert_options reference the same type: ConvertDocumentsRequestOptions.
Problem
Since Pydantic BaseModel does not use extra="forbid", unknown fields are silently ignored:
- User sends
"options": { "pipeline": "vlm", ... } to a chunk endpoint
- Pydantic silently drops
options (unknown field at chunk endpoints)
- Default
ConvertDocumentsRequestOptions() is used instead
- VLM pipeline config, OCR settings, custom prompts -- all ignored
- No error, no warning -- request succeeds with wrong defaults
Real-world impact: I spent significant time debugging why my VLM pipeline prompt overrides were being ignored at chunk endpoints. The root cause was simply that the field is called convert_options there, not options.
Proposed solution
Option A: Rename convert_options to options (preferred)
Use options consistently at all endpoints. The chunk-specific settings are already clearly separated in chunking_options, so there is no naming conflict.
| Before |
After |
Convert: options |
Convert: options (unchanged) |
Chunk: convert_options + chunking_options |
Chunk: options + chunking_options |
Option B: Add extra="forbid" to request models
Add model_config = ConfigDict(extra="forbid") to the base request model. This would raise a Pydantic validation error when unknown fields like options are sent to chunk endpoints, making the mistake immediately obvious.
This would be good practice regardless -- it prevents silent misconfiguration for any field name typo.
Ideally both: Rename for consistency and add extra="forbid" for safety.
Steps to reproduce
import httpx
# This works -- options is the correct field name for convert endpoints
convert_request = {
"options": {"pipeline": "vlm"},
"sources": [{"url": "https://example.com/doc.pdf"}]
}
r = httpx.post("http://localhost:5001/v1/convert/source", json=convert_request)
# Result: VLM pipeline is used correctly
# This SILENTLY FAILS -- options is ignored at chunk endpoints
chunk_request = {
"options": {"pipeline": "vlm"}, # <-- silently dropped!
"chunking_options": {"max_tokens": 512},
"sources": [{"url": "https://example.com/doc.pdf"}]
}
r = httpx.post("http://localhost:5001/v1/chunk/hybrid/source", json=chunk_request)
# Result: default pipeline (standard) is used, VLM config silently ignored
# Correct chunk request requires convert_options instead
chunk_request_correct = {
"convert_options": {"pipeline": "vlm"}, # <-- correct field name
"chunking_options": {"max_tokens": 512},
"sources": [{"url": "https://example.com/doc.pdf"}]
}
Related issues
Source code reference
File: docling_serve/datamodel/requests.py
# Convert endpoints use "options"
class ConvertDocumentsRequest(BaseDocumentsRequest):
options: ConvertDocumentsRequestOptions = ConvertDocumentsRequestOptions()
# Chunk endpoints use "convert_options" for the same type
class HybridChunkerOptionsDocumentsRequest(BaseDocumentsRequest):
convert_options: ConvertDocumentsRequestOptions = ConvertDocumentsRequestOptions()
chunking_options: HybridChunkerOptions = HybridChunkerOptions()
Environment
- docling-serve: v1.9.x / v1.10.x
- Discovered via source code analysis of
docling_serve/datamodel/requests.py
Summary
The convert and chunk endpoints accept the same
ConvertDocumentsRequestOptionsobject, but under different field names. Combined with Pydantic's default behavior of silently ignoring unknown fields, this causes user settings to be dropped without any error or warning.Endpoints and their field names
Convert endpoints -- field:
optionsPOST /v1/convert/sourceConvertDocumentsRequestoptionsPOST /v1/convert/source/asyncConvertDocumentsRequestoptions{ "options": { "pipeline": "vlm", ... }, "sources": [...] }Chunk endpoints -- field:
convert_optionsPOST /v1/chunk/hybrid/sourceHybridChunkerOptionsDocumentsRequestconvert_optionschunking_optionsPOST /v1/chunk/hybrid/source/asyncHybridChunkerOptionsDocumentsRequestconvert_optionschunking_optionsPOST /v1/chunk/hierarchical/sourceHierarchicalChunkerOptionsDocumentsRequestconvert_optionschunking_optionsPOST /v1/chunk/hierarchical/source/asyncHierarchicalChunkerOptionsDocumentsRequestconvert_optionschunking_options{ "convert_options": { "pipeline": "vlm", ... }, "chunking_options": { ... }, "sources": [...] }Both
optionsandconvert_optionsreference the same type:ConvertDocumentsRequestOptions.Problem
Since Pydantic
BaseModeldoes not useextra="forbid", unknown fields are silently ignored:"options": { "pipeline": "vlm", ... }to a chunk endpointoptions(unknown field at chunk endpoints)ConvertDocumentsRequestOptions()is used insteadReal-world impact: I spent significant time debugging why my VLM pipeline prompt overrides were being ignored at chunk endpoints. The root cause was simply that the field is called
convert_optionsthere, notoptions.Proposed solution
Option A: Rename
convert_optionstooptions(preferred)Use
optionsconsistently at all endpoints. The chunk-specific settings are already clearly separated inchunking_options, so there is no naming conflict.optionsoptions(unchanged)convert_options+chunking_optionsoptions+chunking_optionsOption B: Add
extra="forbid"to request modelsAdd
model_config = ConfigDict(extra="forbid")to the base request model. This would raise a Pydantic validation error when unknown fields likeoptionsare sent to chunk endpoints, making the mistake immediately obvious.This would be good practice regardless -- it prevents silent misconfiguration for any field name typo.
Ideally both: Rename for consistency and add
extra="forbid"for safety.Steps to reproduce
Related issues
Source code reference
File:
docling_serve/datamodel/requests.pyEnvironment
docling_serve/datamodel/requests.py