opendatalab/MinerU · warning · TaskWaitAbortedError
Task manager is shutting down
Error message
Task manager is shutting down
What it means
TaskWaitAbortedError('Task manager is shutting down') raised at fast_api.py:1053 branch inside wait_for_terminal_state: after the wait woke up, the task is gone from self.tasks AND self.is_shutting_down is true. It tells the client the wait was aborted because the API server is in graceful shutdown (tasks and events being torn down), not because the task failed. Whatever partial result existed is not retrievable from this manager instance.
Source
Thrown at mineru/cli/fast_api.py:1048
pending: set[asyncio.Task[Any]] = set()
try:
done, pending = await asyncio.wait(
{event_wait_task, manager_wait_task},
return_when=asyncio.FIRST_COMPLETED,
)
finally:
for waiter in pending:
waiter.cancel()
if pending:
await asyncio.gather(*pending, return_exceptions=True)
for waiter in done:
with suppress(asyncio.CancelledError):
waiter.result()
task = self.tasks.get(task_id)
if task is None:
if self.is_shutting_down:
raise TaskWaitAbortedError("Task manager is shutting down")
raise TaskWaitAbortedError("Task was removed before completion")
if is_task_terminal(task.status):
return task
if self.is_shutting_down:
raise TaskWaitAbortedError("Task manager is shutting down")
raise TaskWaitAbortedError(
self.last_worker_error or "Task manager became unavailable while waiting"
)
def get_stats(self) -> dict[str, int]:
stats = {
TASK_PENDING: 0,
TASK_PROCESSING: 0,
TASK_COMPLETED: 0,
TASK_FAILED: 0,
}
for task in self.tasks.values():
if task.status in stats:View on GitHub (pinned to 4fe4bde114)
Solutions
- Treat as retryable: resubmit the parse job to a healthy instance once the server is back.
- Put the API behind a process manager that drains in-flight tasks before shutdown (grace period longer than worst parse time).
- Client-side, distinguish this from a real failure: catch TaskWaitAbortedError and re-enqueue instead of marking the document as failed.
- For very long documents, prefer the async endpoints over the synchronous /file_parse so a shutdown does not drop the whole HTTP wait.
Example fix
# before
result = await client.get(f'{base}/file_parse-result/{task_id}') # wait dies on server shutdown
# after
try:
result = await wait_terminal(task_id)
except TaskWaitAbortedError as exc:
if 'shutting down' in str(exc):
await asyncio.sleep(RESTART_BACKOFF)
task_id = await submit(files) # resubmit after server returns
result = await wait_terminal(task_id) Defensive patterns
Strategy: retry
Try / catch
try:
task = await manager.wait_for_terminal_state(task_id)
except TaskWaitAbortedError as exc:
if 'shutting down' in str(exc):
await wait_server_healthy(base_url)
task_id = await resubmit(files)
task = await manager.wait_for_terminal_state(task_id)
else:
raise Prevention
- Graceful-shutdown drain periods must exceed your longest parse time.
- Prefer async task endpoints for long documents so server restarts do not kill the HTTP wait.
- Teach clients that TaskWaitAbortedError during deploys means resubmit, not document failure.
When it happens
Trigger: Long-polling a task while the server receives SIGTERM/SIGINT or a lifespan shutdown; container orchestrator rolling-restart during an active parse; health-check failure triggering process teardown mid-wait.
Common situations: Kubernetes/container restarts during long VLM parses; CI jobs that ctrl-C the server while a client waits; deploying a new version while requests are in flight.
Related errors
- Task wait handle is unavailable
- Unsupported file type: {file_suffix}
- Failed to load file {upload.original_name}: {exc}
- Task manager is not initialized
- Unknown process_mode: {process_mode}
AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14).
Data as JSON: /api/errors/5a3f58d0f7117939.
Report an issue: GitHub.