{"record":{"id":"95f824777afde2a7","repo":"docling-project/docling","slug":"task-failure-failure-message","errorCode":null,"errorMessage":"{task_failure.failure.message}","messagePattern":"\\{task_failure\\.failure\\.message\\}","errorType":"exception","errorClass":"TaskExecutionError","httpStatus":null,"severity":"error","filePath":"docling/service_client/client.py","lineNumber":695,"sourceCode":"            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\n\n        task_failure = TaskFailureResult.model_validate(payload)\n        raise TaskExecutionError(\n            task_failure.failure.message,\n            failure=task_failure.failure,\n        )\n\n    def _raise_for_generic_http_error(\n        self,\n        response: httpx.Response,\n        message: str,\n    ) -> None:\n        if response.status_code == 402:\n            usage_limit = self._parse_usage_limit_exceeded_response(response)\n            raise UsageLimitExceededError(\n                message,\n                status_code=response.status_code,\n                detail=None if usage_limit is None else usage_limit.message,\n                current_usage=(\n                    None if usage_limit is None else usage_limit.details.currentUsage\n                ),","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/service_client/client.py#L677-L713","documentation":"Raised as TaskExecutionError from _raise_if_task_failure_result when a (JSON) response body carries kind == 'TaskFailureResult'. The message is task_failure.failure.message — the structured failure the service embedded in the response — and the full TaskFailure is attached via the 'failure' kwarg. This path surfaces server-side conversion failures delivered in-band with a response rather than through the status endpoint.","triggerScenarios":"Any response-handling code path that calls _raise_if_task_failure_result (result/status fetches) receiving a JSON body whose payload is a TaskFailureResult envelope; the body parses as JSON, is a dict, and payload['kind'] == 'TaskFailureResult'.","commonSituations":"The service reports conversion failure asynchronously via the response body (e.g. async job result endpoint returning the failure object), invalid or unsupported source documents, or server pipeline exceptions serialized as TaskFailureResult.","solutions":["Read exc.failure for the structured cause (message, code, details) and address the underlying document/pipeline issue.","Re-submit after fixing the input (valid PDF/Office file, correct source descriptor, within limits).","Upgrade docling and docling-serve to matching versions if the failure kind suggests a protocol mismatch.","Log the failure payload with the task_id for server-side correlation in service logs."],"exampleFix":"# before\nresult = job.result()  # TaskExecutionError from in-band TaskFailureResult\n\n# after\nfrom docling.service_client.exceptions import TaskExecutionError\n\ntry:\n    result = job.result()\nexcept TaskExecutionError as exc:\n    if exc.failure is not None:\n        log.warning(\"failure code=%s msg=%s\", exc.failure.code, exc.failure.message)\n    raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from docling.service_client.exceptions import TaskExecutionError\n\ntry:\n    result = job.result()\nexcept TaskExecutionError as exc:\n    if exc.failure is not None:\n        record_failure(exc.failure)  # structured payload\n    raise","preventionTips":["Log the failure payload with task_id for correlation.","Keep client and service versions aligned to avoid protocol surprises.","Quarantine inputs that repeatedly produce TaskFailureResult.","Handle this alongside the status-based failure path with one shared except."],"tags":["task","failure","service-client","json"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}