opendatalab/MinerU · error · ValueError

middle_json must contain a list field named pdf_info.

Error message

middle_json must contain a list field named pdf_info.

What it means

ValueError from regenerate_client_side_outputs(): the pdf_info field of the middle json must be a list (one entry per page). Even when _backend is valid, a missing pdf_info (None), an object, or a scalar aborts client-side rendering before union_make is called.

Source

Thrown at mineru/cli/client_side_output.py:68

    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),
        encoding="utf-8",
    )
    _write_json(
        content_list_path,
        make_func(pdf_info, MakeMode.CONTENT_LIST, image_dir),
    )
    _write_json(
        content_list_v2_path,

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Regenerate the middle json with a matching mineru version
  2. If constructing the file manually, ensure pdf_info is a JSON array of page objects
  3. Pre-validate the parsed structure (isinstance checks) before calling regenerate (see defense)
  4. Avoid renaming/deleting keys when post-processing staged artifacts

Example fix

# before: {"_backend": "vlm", "pdf_info": {"0": {...}}}

# after: {"_backend": "vlm", "pdf_info": [{...}]}
Defensive patterns

Strategy: type-guard

Validate before calling

pdf_info = json.loads(middle_json_path.read_text("utf-8")).get("pdf_info")
if not isinstance(pdf_info, list):
    raise SystemExit("middle json schema mismatch: pdf_info must be a list; regenerate artifacts")

Type guard

def has_pdf_info_list(payload: dict) -> bool:
    return isinstance(payload.get("pdf_info"), list)

Try / catch

try:
    regenerate_client_side_outputs(parse_dir, doc_stem)
except ValueError as e:
    if "pdf_info" in str(e):
        refetch_results()
    else:
        raise

Prevention

When it happens

Trigger: A middle json where 'pdf_info' was renamed, removed by a cleanup script, or replaced by a dict keyed by page number; also fires when the key exists but holds null.

Common situations: Downstream tools rewriting middle.json with a different schema; partial manual migration of old outputs; server versions that emit a differently-named field.

Related errors


AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14). Data as JSON: /api/errors/dec292e46b499e57. Report an issue: GitHub.