HKUDS/DeepTutor · error · MinerUError

MinerU API did not return an upload URL (missing batch_id/fi

Error message

MinerU API did not return an upload URL (missing batch_id/file_urls).

What it means

The MinerU batch-creation endpoint responded, but its data payload lacked batch_id or file_urls, so there is no upload URL to PUT the PDF to.

Source

Thrown at deeptutor/services/parsing/engines/mineru/cloud.py:140

    client: httpx.Client, pdf_path: Path, config: MinerUConfig, key_pool: KeyPool
) -> tuple[str, str]:
    """POST file-urls/batch → ``(batch_id, signed_upload_url)``."""
    file_entry: dict[str, object] = {"name": pdf_path.name, "is_ocr": config.is_ocr}
    body: dict[str, object] = {
        "files": [file_entry],
        "model_version": config.model_version,
        "enable_formula": config.enable_formula,
        "enable_table": config.enable_table,
    }
    if config.api_language:
        body["language"] = config.api_language

    payload = _post_json(client, "/api/v4/file-urls/batch", body, key_pool)
    data = payload.get("data") or {}
    batch_id = str(data.get("batch_id") or "").strip()
    file_urls = data.get("file_urls") or []
    if not batch_id or not isinstance(file_urls, list) or not file_urls:
        raise MinerUError("MinerU API did not return an upload URL (missing batch_id/file_urls).")
    return batch_id, str(file_urls[0])


def _upload_file(pdf_path: Path, upload_url: str) -> None:
    """PUT the PDF bytes to the signed URL.

    The signed URL carries its own auth; per MinerU's docs we must NOT send an
    ``Authorization`` or ``Content-Type`` header (a stray Content-Type breaks
    the OSS signature).
    """
    data = pdf_path.read_bytes()
    try:
        response = httpx.put(upload_url, content=data, timeout=_UPLOAD_TIMEOUT_SECONDS)
        response.raise_for_status()
    except httpx.HTTPError as exc:
        raise MinerUError(f"Failed to upload PDF to MinerU: {exc}") from exc

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Log the full payload for that response and compare with MinerU API docs.
  2. Confirm config.api_base_url points at a supported API version (v4).
  3. Retry once — transient malformed responses happen.
  4. Report to MinerU if consistently malformed.
Defensive patterns

Strategy: retry

Try / catch

try:
    parse_cloud(...)
except MinerUError as e:
    if "upload URL" in str(e):
        time.sleep(5); parse_cloud(...)  # fresh batch

Prevention

When it happens

Trigger: POST /api/v4/file-urls/batch returning 200 with malformed data — API contract change, empty file_urls list, or stripped batch_id.

Common situations: MinerU API version drift, backend incident returning partial payloads, or a region-specific endpoint behaving differently (api_base_url override).

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/924f8c791ce1313f. Report an issue: GitHub.