{"record":{"id":"3da8e1138a67ad92","repo":"opendatalab/MinerU","slug":"task-manager-is-not-initialized","errorCode":null,"errorMessage":"Task manager is not initialized","messagePattern":"Task manager is not initialized","errorType":"http","errorClass":"HTTPException","httpStatus":503,"severity":"error","filePath":"mineru/cli/fast_api.py","lineNumber":1224,"sourceCode":"    def _is_task_expired(self, task: AsyncParseTask, now: datetime) -> bool:\n        if task.status not in (TASK_COMPLETED, TASK_FAILED):\n            return False\n        if not task.completed_at:\n            return False\n        try:\n            completed_at = datetime.fromisoformat(task.completed_at)\n        except ValueError:\n            logger.warning(f\"Invalid completed_at for task {task.task_id}: {task.completed_at}\")\n            return False\n        if completed_at.tzinfo is None:\n            completed_at = completed_at.replace(tzinfo=timezone.utc)\n        return (now - completed_at).total_seconds() >= self.task_retention_seconds\n\n\ndef get_task_manager() -> AsyncTaskManager:\n    task_manager = getattr(app.state, \"task_manager\", None)\n    if task_manager is None:\n        raise HTTPException(status_code=503, detail=\"Task manager is not initialized\")\n    return task_manager\n\n\n@app.post(\n    path=\"/file_parse\",\n    status_code=200,\n    summary=\"Synchronously parse uploaded files\",\n    description=(\n        \"Submit a parsing task to the shared async task manager, wait for it to \"\n        \"finish, and return the final parsing result in the same response.\"\n    ),\n)\nasync def parse_pdf(\n    http_request: Request,\n    background_tasks: BackgroundTasks,\n    request_options: Annotated[\n        ParseRequestOptions, Depends(parse_request_form)\n    ],","sourceCodeStart":1206,"sourceCodeEnd":1242,"githubUrl":"https://github.com/opendatalab/MinerU/blob/4fe4bde114a23ee5dd637eae99b767f4669bf58c/mineru/cli/fast_api.py#L1206-L1242","documentation":"HTTP 503 raised by get_task_manager() in fast_api.py when app.state.task_manager is None (or missing). The AsyncTaskManager is created during the FastAPI lifespan/startup hook; if a request is served before lifespan ran, or lifespan failed partway, every task endpoint returns 503 with this detail. It is a server-initialization problem, never a client-input problem.","triggerScenarios":"Using fastapi.testclient.TestClient or httpx ASGI transport without entering the lifespan context (no 'with TestClient(app) as c:'); mounting the mineru app inside another app without running its lifespan; lifespan startup crashed (e.g. model load failure) but the process still serves; importing the app module and running it with a server that skips lifespan.","commonSituations":"Writing tests against the API without lifespan; embedding the app in a larger service; startup errors being swallowed so the app runs half-initialized; exotic ASGI servers with lifespan disabled.","solutions":["Ensure requests only flow after startup: with TestClient(app) as client: ... (the with-block triggers lifespan).","Check the server startup logs for the underlying lifespan exception (model download, CUDA init, port issues) and fix that first.","If embedding the app, run its lifespan or set app.state.task_manager explicitly before serving traffic.","Retry with backoff on 503 from orchestrators that start before the app is warm."],"exampleFix":"# before (test never initializes the manager)\nclient = TestClient(app)\nr = client.get('/tasks/abc')  # 503 Task manager is not initialized\n\n# after\nwith TestClient(app) as client:  # enters lifespan, manager created\n    r = client.get('/tasks/abc')  # 404 Task not found — manager alive","handlingStrategy":"validation","validationCode":"# before any request in tests/embeddings, verify lifespan ran\nfrom fastapi.testclient import TestClient\nwith TestClient(app) as client:  # enters lifespan -> task_manager created\n    client.get('/tasks/abc')","typeGuard":"def task_manager_ready(app) -> bool:\n    return getattr(app.state, 'task_manager', None) is not None","tryCatchPattern":"r = client.get(f'{base}/tasks/{task_id}')\nif r.status_code == 503:\n    raise RuntimeError('API not warmed up / lifespan failed — check startup logs')","preventionTips":["Always use context-managed clients (with TestClient(app) as ...) so lifespan executes.","Health-check the app after startup and before routing user traffic.","When embedding the app, run its lifespan or construct the task manager explicitly."],"tags":["mineru","fastapi","lifespan","initialization","http-503"],"backgroundTag":null,"analyzedSha":"4fe4bde114a23ee5dd637eae99b767f4669bf58c","analyzedAt":"2026-08-14T21:29:18.456Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}