docling-project/docling · error · ValueError
Invalid JSON for nested config field: {exc}
Error message
Invalid JSON for nested config field: {exc} What it means
Field validator (mode='before') on the docling service options: when a nested configuration field arrives as a string, it is parsed with json.loads; if parsing fails, this ValueError is raised with the underlying JSONDecodeError detail. It exists because multipart/form-data submissions (local-file conversions) must serialize nested configs as JSON strings, and malformed strings are caught here rather than deep inside Pydantic.
Source
Thrown at docling/datamodel/service/options.py:900
"table_structure_custom_config",
"layout_custom_config",
"picture_classification_custom_config",
mode="before",
)
@classmethod
def _decode_json_string_config(cls, value: Any) -> Any:
"""Accept a JSON-encoded string for nested config fields.
Local-file conversions submit options as ``multipart/form-data``, where
nested configs are sent as JSON strings because form fields cannot carry
objects. Decode them back into dicts here. Values that already arrive as
objects (e.g. via JSON request bodies) are returned unchanged.
"""
if isinstance(value, str):
try:
return json.loads(value)
except json.JSONDecodeError as exc:
raise ValueError(
f"Invalid JSON for nested config field: {exc}"
) from exc
return value
# Field validators for deprecated fields - trigger warnings on assignment
@field_validator("picture_description_api", mode="before")
@classmethod
def validate_picture_description_api(cls, v):
"""Emit deprecation warning when picture_description_api is set."""
if v is not None:
warnings.warn(
"picture_description_api is deprecated. "
"Please migrate to picture_description_preset or "
"picture_description_custom_config.",
DeprecationWarning,
stacklevel=2,
)
return vView on GitHub (pinned to 61d76f1ff3)
Solutions
- Ensure every nested config sent as a form field is serialized with json.dumps (never str(dict)).
- Validate the string with json.loads client-side before sending.
- Prefer the JSON request body endpoint when sending complex nested options.
- Check the exc detail in the message for the exact character position of the JSON syntax error.
Example fix
# before
requests.post(url, files=files, data={'pipeline_options': str(options_dict)}) # single quotes -> invalid JSON
# after
import json
requests.post(url, files=files, data={'pipeline_options': json.dumps(options_dict)}) Defensive patterns
Strategy: validation
Validate before calling
import json
def valid_nested_config_strings(payload: dict) -> bool:
nested = ('pipeline_options',) # keys your client sends as form strings
return all(
not isinstance(v, str) or _is_json(v)
for k, v in payload.items() if k in nested
)
def _is_json(s: str) -> bool:
try:
json.loads(s)
return True
except json.JSONDecodeError:
return False Try / catch
try:
resp = requests.post(url, files=files, data=form)
except ValueError:
# client-side: validate form strings with json.loads before sending
pass Prevention
- Always serialize nested form fields with json.dumps, never str(dict).
- Round-trip check: json.loads(json.dumps(obj)) before submission.
- Use the JSON request body endpoint for complex nested options.
When it happens
Trigger: POSTing to the service with multipart/form-data where a nested field (e.g., pipeline options or a nested config object) contains invalid JSON — missing quotes, trailing commas, single quotes, unescaped newlines. Does not fire for JSON request bodies, which arrive as real objects.
Common situations: Hand-built curl multipart forms; client code that str()-dumps a Python dict into a form field instead of json.dumps; form values truncated by proxies or shell quoting issues.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ZIP URLs are not accepted on the convert endpoint
- The parameters picture_description_local and picture_descrip
- The parameters vlm_pipeline_model, vlm_pipeline_model_local
- Cannot specify both vlm_pipeline_preset and vlm_pipeline_cus
- Cannot mix legacy VLM options (vlm_pipeline_model*) with new
AI-assisted analysis of docling-project/docling@61d76f1ff3 (2026-08-14).
Data as JSON: /api/errors/b6594a60475deaf7.
Report an issue: GitHub.