{"record":{"id":"10757060aee6b0c7","repo":"docling-project/docling","slug":"result-for-task-task-id-is-not-ready","errorCode":null,"errorMessage":"Result for task {task_id} is not ready.","messagePattern":"Result for task (.+?) is not ready\\.","errorType":"exception","errorClass":"ResultNotReadyError","httpStatus":null,"severity":"warning","filePath":"docling/service_client/client.py","lineNumber":674,"sourceCode":"        now = datetime.now(tz=retry_at.tzinfo or timezone.utc)\n        return max(0.0, (retry_at - now).total_seconds())\n\n    def _raise_for_result_404(\n        self,\n        task_id: str,\n        response: httpx.Response,\n        last_status: TaskStatusResponse | None,\n    ) -> None:\n        detail = self._http_error_detail(response)\n        if detail == \"Task not found.\":\n            raise TaskNotFoundError(f\"Task {task_id} was not found.\")\n        if detail is not None and detail.startswith(\"Task result not found\"):\n            if last_status is not None and is_terminal_task_status(last_status):\n                if last_status.task_status == \"failure\":\n                    message = last_status.error_message or f\"Task {task_id} failed.\"\n                    raise TaskExecutionError(message, failure=last_status.failure)\n                raise ResultExpiredError(f\"Result for task {task_id} has expired.\")\n            raise ResultNotReadyError(f\"Result for task {task_id} is not ready.\")\n        raise ServiceError(\n            \"Unexpected result lookup error.\",\n            status_code=response.status_code,\n            detail=detail,\n        )\n\n    def _raise_if_task_failure_result(self, response: httpx.Response) -> None:\n        content_type = response.headers.get(\"content-type\", \"\")\n        if \"json\" not in content_type.lower():\n            return\n\n        try:\n            payload = response.json()\n        except ValueError:\n            return\n\n        if not isinstance(payload, dict) or payload.get(\"kind\") != \"TaskFailureResult\":\n            return","sourceCodeStart":656,"sourceCodeEnd":692,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/service_client/client.py#L656-L692","documentation":"Raised as ResultNotReadyError when the result endpoint returns 'Task result not found' but the task is not in a terminal state — the conversion is still running (or its status is unknown). It is the client's signal that the caller asked for a result too early and should wait/poll again rather than treat it as a hard failure.","triggerScenarios":"Fetching /v1/result/{task_id} (e.g. via an impatient result() call or race between status polling and result fetch) while the task is still queued or processing; last_status is None or non-terminal, so the 404 'Task result not found' maps to 'not ready' instead of expired/failed.","commonSituations":"Large documents with long processing times, callers skipping the wait/poll phase, concurrency contention slowing the pipeline, or short poll timeouts causing premature result fetches.","solutions":["Catch ResultNotReadyError and loop: wait, re-check task status, then retry result retrieval.","Increase the timeout/poll wait you pass to job.result(...) so the client waits for terminal status internally.","Reduce conversion latency with max_num_pages/page_range or smaller files so results appear sooner.","For many tasks, collect results only after status polling reports terminal states."],"exampleFix":"# before\nresult = job.result()  # raises ResultNotReadyError while task is processing\n\n# after\nfrom docling.service_client.exceptions import ResultNotReadyError\nimport time\n\nwhile True:\n    try:\n        result = job.result()\n        break\n    except ResultNotReadyError:\n        time.sleep(2)\n        continue","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"from docling.service_client.exceptions import ResultNotReadyError\nimport time\n\nwhile True:\n    try:\n        result = job.result()\n        break\n    except ResultNotReadyError:\n        time.sleep(poll_interval)  # still processing; wait and retry","preventionTips":["Pass an adequate timeout to job.result() so the client waits internally.","Poll status to terminal before fetching results.","Keep poll_interval modest (1-5s) and bounded by an overall deadline.","Reduce document size to shorten processing time."],"tags":["task","not-ready","polling","service-client"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}