{"record":{"id":"792861970fc9a0b4","repo":"zylon-ai/private-gpt","slug":"task-failed-with-status-status-task-status","errorCode":null,"errorMessage":"Task failed with status: {status.task_status}","messagePattern":"Task failed with status: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/readers/docling/api_clients.py","lineNumber":498,"sourceCode":"            session.get(\n                f\"{self.base_url}/result/{task_id}\", headers=headers\n            ) as response,\n        ):\n            response.raise_for_status()\n            result = await response.json()\n            return DoclingApiOutputModel(**result)\n\n    async def _wait_for_completion(self, task_id: str) -> DoclingApiOutputModel:\n        start_time = time.time()\n        while not self.poll_timeout or time.time() - start_time < self.poll_timeout:\n            status = await self._poll_task_status(task_id)\n            if status.task_status == \"success\":\n                task_result: DoclingApiOutputModel = await self._get_task_result(\n                    task_id\n                )\n                return task_result\n            if status.task_status in [\"failure\", \"skipped\"]:\n                raise ValueError(f\"Task failed with status: {status.task_status}\")\n\n            await asyncio.sleep(self.poll_interval)\n\n        raise TimeoutError(f\"Task did not complete within {self.poll_timeout} seconds\")\n\n    @retry(\n        is_async=True,\n        tries=_MAX_RETRIES,\n        jitter=_JITTER,\n        logger=logger,\n        exceptions=ResourceNotFoundError,\n    )\n    async def convert_from_bytes(\n        self, file_name: str, file_bytes: bytes, **kwargs: Any\n    ) -> DoclingApiOutputModel:\n        task_id = await self._submit_task(file_name, file_bytes, **kwargs)\n        return await self._wait_for_completion(task_id)\n","sourceCodeStart":480,"sourceCodeEnd":516,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/readers/docling/api_clients.py#L480-L516","documentation":"Raised by AsyncDoclingClient._wait_for_completion when the Docling server reports a terminal task_status of 'failure' or 'skipped' for a submitted async conversion task. The client had successfully submitted the file to /convert/source/async and received a task_id, but the server-side conversion itself failed or the task was skipped. This is a server-side outcome being surfaced to the caller as a ValueError; the message includes the exact status string.","triggerScenarios":"Calling convert_from_bytes on AsyncDoclingClient (i.e., docling async ingestion) where the Docling server processes the task and returns task_status == 'failure' (conversion error, e.g., corrupt PDF backend, invalid options) or 'skipped' (task superseded/removed, e.g., server restart with queue cleanup or duplicate job).","commonSituations":"Corrupt or password-protected PDFs; unsupported from_formats/pdf_backend options (e.g., pdf_backend not available on the server build); Docling server version mismatch where options like do_code_enrichment are rejected at conversion time; server restart purging the task queue; GPU/OCR model crash on the server while processing a specific document.","solutions":["Check the Docling server logs for the actual conversion error for that task_id — this exception only mirrors the server's status.","Verify the conversion options sent (pdf_backend, from_formats, to_formats, ocr settings) are supported by your Docling server version; try pdf_backend='dlparse_v2' defaults.","Test the same file directly against the server API (POST /convert/source/async then GET /status/poll/{id}) to isolate whether the file itself is the problem.","Try the file with a different pdf_backend or with do_ocr toggled, since OCR crashes are a frequent cause of 'failure' status.","If 'skipped' recurs, check for server restarts or queue misconfiguration between submission and polling."],"exampleFix":"# before\nresult = await client.convert_from_bytes(name, data)\n\n# after\ntry:\n    result = await client.convert_from_bytes(name, data)\nexcept ValueError as e:\n    if 'Task failed with status' in str(e):\n        logger.error(\"Docling server rejected %s: %s\", name, e)\n        raise DocumentUnprocessableError(name) from e\n    raise","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    result = await client.convert_from_bytes(file_name, file_bytes)\nexcept ValueError as e:\n    status = str(e).rsplit(\":\", 1)[-1].strip()  # 'failure' or 'skipped'\n    if status in (\"failure\", \"skipped\"):\n        quarantine_file(file_name, reason=f\"docling task {status}\")\n        return None  # skip, do not retry: terminal server-side outcome\n    raise","preventionTips":["Keep the Docling server version aligned with the options private-gpt sends (pdf_backend, from_formats).","Log task_id at submission so server logs can be correlated when a task fails.","Quarantine files that consistently fail instead of re-submitting them."],"tags":["docling","async","task-status","server-side-failure"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}