opendatalab/MinerU · error · HTTPException

{detail}

Error message

{detail}

What it means

HTTPException that re-raises the upstream's non-200 status and body verbatim when fetching a task result. The upstream response body (or reason phrase if empty) becomes the error detail, and the failure is recorded on the task record.

Solutions

  1. Read the status code and detail — they come straight from the upstream result endpoint
  2. If 404 upstream: the result no longer exists there (restart/eviction); re-submit the task
  3. Check upstream logs for the matching request; fix upstream result retention/storage if results vanish
Defensive patterns

Strategy: try-catch

Try / catch

r = client.get(f"{router}/tasks/{task_id}/result")
if r.status_code == 404:
    resubmit(files)  # upstream lost the result; nothing to fetch
elif r.status_code >= 500:
    retry_with_backoff(lambda: client.get(f"{router}/tasks/{task_id}/result"))

Prevention

When it happens

Trigger: GET {upstream}/tasks/{id}/result returns e.g. 404 (result evicted upstream), 403, or 500; the router reads the body, closes the stream, and returns the same status/detail to the client.

Common situations: Upstream restarted and lost the finished result; result retention on the upstream expired; upstream error during result assembly. The status code is upstream's, so it identifies the true cause.

Related errors


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

Appendix: source

Thrown at mineru/cli/router.py:1320

                "GET",
                result_url,
                timeout=build_result_download_timeout(),
            ),
            stream=True,
        )
    except httpx.HTTPError as exc:
        await request.app.state.router_task_registry.increment_upstream_error(task.task_id, str(exc))
        raise HTTPException(status_code=502, detail=str(exc)) from exc

    if upstream_response.status_code != 200:
        body = await upstream_response.aread()
        await upstream_response.aclose()
        detail = body.decode("utf-8", errors="replace").strip() or upstream_response.reason_phrase
        await request.app.state.router_task_registry.increment_upstream_error(
            task.task_id,
            f"{upstream_response.status_code} {detail}",
        )
        raise HTTPException(
            status_code=upstream_response.status_code,
            detail=detail,
        )

    content_type = upstream_response.headers.get("content-type", "")
    if "application/json" in content_type:
        body = await upstream_response.aread()
        await upstream_response.aclose()
        return Response(
            content=body,
            status_code=200,
            media_type="application/json",
        )

    headers: dict[str, str] = {}
    content_disposition = upstream_response.headers.get("content-disposition")
    if content_disposition:
        headers["content-disposition"] = content_disposition

View on GitHub (pinned to 4fe4bde114)