opendatalab/MinerU · critical · RuntimeError
No healthy upstream MinerU API servers are available
Error message
No healthy upstream MinerU API servers are available
What it means
Raised at router startup when the WorkerPool health check reports no healthy upstream MinerU API servers. The router refuses to start (and shuts down the registry, worker pool, and http client) because every configured upstream failed its health probe. The message may come from the health payload's 'error' key, defaulting to this string.
Source
Thrown at mineru/cli/router.py:999
async def startup_router_state(app: FastAPI, settings: RouterSettings) -> None:
http_client = httpx.AsyncClient(
timeout=build_http_timeout(),
follow_redirects=True,
)
worker_pool = WorkerPool(settings, http_client)
registry = RouterTaskRegistry(
task_retention_seconds=settings.task_retention_seconds,
cleanup_interval_seconds=settings.task_cleanup_interval_seconds,
)
try:
await registry.start()
await worker_pool.start()
healthy, payload = worker_pool.health_payload()
if not healthy:
raise RuntimeError(
payload.get(
"error",
"No healthy upstream MinerU API servers are available",
)
)
except Exception:
await registry.shutdown()
await worker_pool.shutdown()
await http_client.aclose()
raise
app.state.http_client = http_client
app.state.worker_pool = worker_pool
app.state.router_task_registry = registry
async def shutdown_router_state(app: FastAPI) -> None:
registry = getattr(app.state, "router_task_registry", None)View on GitHub (pinned to 4fe4bde114)
Solutions
- Start or fix the upstream MinerU API servers and verify each /health endpoint returns healthy with curl before starting the router
- Correct the server URL list in the router configuration (scheme, host, port)
- If servers are slow to boot, start them first or add readiness checks so the router starts after upstreams are healthy
- Check network/DNS/firewall between the router host and each upstream server
Example fix
# before MINERU_SERVER_URLS=http://localhost:8000 # server not running # after # start upstream first, verify, then run router curl -fsS http://localhost:8000/health MINERU_SERVER_URLS=http://localhost:8000 mineru-api-router
Defensive patterns
Strategy: validation
Validate before calling
import httpx
def upstreams_healthy(server_urls: list[str], timeout: float = 5.0) -> bool:
with httpx.Client(timeout=timeout) as c:
return all(
c.get(f"{u.rstrip('/')}/health").status_code == 200
for u in server_urls
) Try / catch
try:
app = create_router_app(settings)
except RuntimeError as exc:
if "No healthy upstream" in str(exc):
log.error("upstreams down; not starting router")
raise Prevention
- Run health checks (curl /health) on every upstream before starting the router
- Keep upstream servers under a supervisor (systemd/docker restart policy) so they recover automatically
- Point MINERU_SERVER_URLS at a load balancer with its own health checks
- Alert on upstream health so the router never starts into a dead pool
When it happens
Trigger: Calling create_app/router startup with MINERU_SERVER_URLS (or equivalent settings) pointing at servers that are down, unreachable, or return non-healthy /health responses; worker_pool.health_payload() returns healthy=False during lifespan startup.
Common situations: Upstream MinerU API processes not started yet; wrong host/port in server list; firewall or DNS blocking the health endpoint; upstream containers still booting when the router starts; all servers previously marked unhealthy.
Related errors
- MinerU upstream returned an invalid submit payload
- Invalid submit payload: {exc}
- {exc.detail}
- {detail}
- Local worker {server_id} exited before becoming healthy
AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14).
Data as JSON: /api/errors/9df6a45066225501.
Report an issue: GitHub.