opendatalab/MinerU · error · ValueError

MinerU upstream returned an invalid submit payload

Error message

MinerU upstream returned an invalid submit payload

What it means

parse_submit_response raises ValueError when the upstream submit endpoint returns a 202 whose JSON body is not a JSON object (e.g. a list, string, or number). The router strictly validates the submit response shape before registering the task.

Source

Thrown at mineru/cli/router.py:1097

                        field_name=key,
                        upload_name=original_name,
                        content_type=value.content_type or "application/octet-stream",
                        path=str(destination),
                    )
                )
                await value.close()
            else:
                fields.append((key, str(value)))
    except Exception:
        cleanup_path(temp_dir)
        raise

    return MultipartPayload(temp_dir=temp_dir, fields=fields, uploads=uploads)


def parse_submit_response(payload: Any) -> dict[str, Any]:
    if not isinstance(payload, dict):
        raise ValueError("MinerU upstream returned an invalid submit payload")
    task_id = payload.get("task_id")
    status = payload.get("status")
    backend = payload.get("backend")
    created_at = payload.get("created_at")
    if not isinstance(task_id, str) or not isinstance(status, str) or not isinstance(backend, str):
        raise ValueError("MinerU upstream returned an invalid submit payload")
    if created_at is not None and not isinstance(created_at, str):
        raise ValueError("MinerU upstream returned an invalid submit payload")
    return {
        "task_id": task_id,
        "status": status,
        "backend": backend,
        "file_names": payload.get("file_names", []),
        "created_at": created_at or utc_now_iso(),
        "started_at": payload.get("started_at"),
        "completed_at": payload.get("completed_at"),
        "error": payload.get("error"),
        "queued_ahead": payload.get("queued_ahead") if isinstance(payload.get("queued_ahead"), int) else None,

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Inspect the actual upstream response body for POST /tasks and compare with the expected {task_id, status, backend, ...} object
  2. Verify the upstream is a compatible MinerU API server version
  3. Remove any intermediary that rewrites the response body
Defensive patterns

Strategy: validation

Validate before calling

import httpx

def submit_ok(base_url: str, files) -> dict:
    with httpx.Client() as c:
        r = c.post(f"{base_url}/tasks", files=files)
        body = r.json()
        assert r.status_code == 202 and isinstance(body, dict), body
        return body

Type guard

def is_submit_payload(v) -> bool:
    return isinstance(v, dict)

Prevention

When it happens

Trigger: POST {base_url}/tasks returns 202 with a top-level JSON array, string, or scalar instead of an object; or a proxy in front of the upstream rewrites the response body.

Common situations: A custom or incompatible MinerU upstream version that returns a different response envelope; an API gateway that transforms responses; the URL points at a non-MinerU service that accepts POSTs.

Related errors


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