opendatalab/MinerU · error · HTTPException

{exc.detail}

Error message

{exc.detail}

What it means

HTTPException that propagates an UpstreamSubmissionRejected: the upstream answered POST /tasks with a definitive non-retryable, non-202 status (anything outside 202 and HTTP_RETRYABLE_STATUS_CODES). The upstream's status code and body detail are passed through to the client.

Source

Thrown at mineru/cli/router.py:1223

                list(file_names)
                if isinstance(file_names, list) and all(isinstance(item, str) for item in file_names)
                else []
            )
            return await registry.register(
                upstream_server_id=server.server_id,
                upstream_base_url=server.base_url,
                upstream_task_id=upstream_payload["task_id"],
                backend=upstream_payload["backend"],
                file_names=normalized_file_names,
                created_at=upstream_payload["created_at"],
                status=upstream_payload["status"],
                started_at=upstream_payload["started_at"] if isinstance(upstream_payload["started_at"], str) else None,
                completed_at=upstream_payload["completed_at"] if isinstance(upstream_payload["completed_at"], str) else None,
                error=upstream_payload["error"] if isinstance(upstream_payload["error"], str) else None,
                queued_ahead=upstream_payload["queued_ahead"],
            )
        except UpstreamSubmissionRejected as exc:
            raise HTTPException(status_code=exc.status_code, detail=exc.detail) from exc
        except UpstreamSubmissionUnavailable as exc:
            attempted_servers.add(server.server_id)
            last_error = f"Failed to submit task via {server.server_id}: {exc}"
            await worker_pool.mark_submission_failure(server.server_id, str(exc))
        finally:
            await worker_pool.release_submission_server(server.server_id)


async def fetch_router_task_status(
    request: Request,
    task: RouterTaskRecord,
) -> RouterTaskRecord:
    if is_task_terminal(task.status):
        return task

    registry: RouterTaskRegistry = request.app.state.router_task_registry
    client: httpx.AsyncClient = request.app.state.http_client
    url = f"{task.upstream_base_url}{TASKS_ENDPOINT}/{task.upstream_task_id}"

View on GitHub (pinned to 4fe4bde114)

Solutions

  1. Read the returned status code and detail — it mirrors the upstream rejection reason (e.g. 413 payload too large)
  2. Fix the client-side request: file type, size limits, or parameters per the upstream API
  3. If the rejection seems wrong, inspect the upstream server logs for the same request
Defensive patterns

Strategy: try-catch

Validate before calling

# client-side preflight: reject unsupported/oversized files before submitting
ALLOWED = {'.pdf', '.doc', '.docx', '.ppt', '.pptx'}
MAX_BYTES = 200 * 1024 * 1024

def file_ok(path) -> bool:
    return path.suffix.lower() in ALLOWED and path.stat().st_size <= MAX_BYTES

Try / catch

resp = client.post(f"{router}/tasks", files=files)
if resp.status_code >= 400:
    detail = resp.json().get('detail', '')
    if resp.status_code == 413:
        compress_or_split(files)
    else:
        raise SubmissionRejected(resp.status_code, detail)  # do not retry 4xx

Prevention

When it happens

Trigger: Upstream returns e.g. 400/413/422 to the submit request (invalid params, file too large) — router re-raises HTTPException(exc.status_code, exc.detail) instead of failing over.

Common situations: Client submits an unsupported file type or oversized multipart body; upstream rejects authentication; version mismatch changes the submit contract. Because rejection is definitive, the router does not try other servers.

Related errors


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