opendatalab/MinerU · error · ValueError
middle_json must be a dict.
Error message
middle_json must be a dict.
What it means
ValueError from regenerate_client_side_outputs(): after json.loads of the middle json, the top-level value must be a dict (the code immediately reads .get('_backend') and .get('pdf_info')). A JSON array, string, number, or null at the top level fails this check.
Source
Thrown at mineru/cli/client_side_output.py:60
def regenerate_client_side_outputs(
parse_dir: str | Path,
doc_stem: str,
) -> tuple[Path, ...]:
"""读取服务端 staged/finalized middle json,并在客户端覆盖生成最终输出产物。"""
parse_dir = Path(parse_dir)
middle_json_path = parse_dir / f"{doc_stem}_middle.json"
markdown_path = parse_dir / f"{doc_stem}.md"
content_list_path = parse_dir / f"{doc_stem}_content_list.json"
content_list_v2_path = parse_dir / f"{doc_stem}_content_list_v2.json"
if not middle_json_path.exists():
raise FileNotFoundError(f"Missing middle json file: {middle_json_path}")
middle_json = json.loads(middle_json_path.read_text(encoding="utf-8"))
if not isinstance(middle_json, dict):
raise ValueError("middle_json must be a dict.")
backend = middle_json.get("_backend")
pdf_info = middle_json.get("pdf_info")
if backend not in SUPPORTED_BACKENDS:
raise ValueError(
f"Unsupported middle json backend for client-side output generation: {backend}"
)
if not isinstance(pdf_info, list):
raise ValueError("middle_json must contain a list field named pdf_info.")
if backend in PDF_BACKENDS:
finalize_client_side_middle_json(middle_json)
pdf_info = middle_json["pdf_info"]
make_func = _select_union_make(backend)
image_dir = "images"
markdown_path.write_text(
make_func(pdf_info, MakeMode.MM_MD, image_dir),View on GitHub (pinned to 4fe4bde114)
Solutions
- Regenerate the middle json with a current mineru server so it is wrapped in an object with _backend and pdf_info keys
- If producing middle json yourself, emit {"_backend": "pipeline", "pdf_info": [...]}
- Validate the shape in a pre-check before calling regenerate (see defense below)
Example fix
# before: middle.json contains just [ {...page1...}, {...page2...} ]
# after: {"_backend": "pipeline", "pdf_info": [ {...page1...}, {...page2...} ]} Defensive patterns
Strategy: type-guard
Validate before calling
payload = json.loads(middle_json_path.read_text(encoding="utf-8"))
if not isinstance(payload, dict):
raise SystemExit("middle json schema mismatch: top level must be an object; regenerate with current mineru") Type guard
def is_middle_json_dict(payload: object) -> bool:
return isinstance(payload, dict) Try / catch
try:
regenerate_client_side_outputs(parse_dir, doc_stem)
except ValueError as e:
if "must be a dict" in str(e):
refetch_results() # schema is foreign/stale; do not try to patch it
else:
raise Prevention
- Never hand-write middle.json; always produce it via mineru
- If post-processing, round-trip through json and assert the object shape
- Pin server/client versions so the schema cannot drift
When it happens
Trigger: A {doc}_middle.json whose top level is a list (e.g. a bare pdf_info array serialized by an old version or a custom exporter) or a truncated/corrupted file that still parses as valid non-dict JSON (rare); most corruption instead raises JSONDecodeError one line earlier.
Common situations: Hand-rolled middle-json producers that dump the page array directly; third-party tools writing their own _middle.json; files from very old mineru versions with a different schema.
Related errors
- middle_json must contain a list field named pdf_info.
- Unsupported middle json backend for client-side output gener
- Missing middle json file: {middle_json_path}
- max_concurrent_requests must be a positive integer
- effort must be "medium" or "high"
AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14).
Data as JSON: /api/errors/23fe89ac8684e1fc.
Report an issue: GitHub.