{"record":{"id":"7769f91b6b5b2efd","repo":"BerriAI/litellm","slug":"wxo-run-ended-with-non-success-status-status","errorCode":null,"errorMessage":"WXO run ended with non-success status '{status}': {run_data}","messagePattern":"WXO run ended with non-success status '(.+?)': (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"litellm/a2a_protocol/providers/watsonx_orchestrate/handler.py","lineNumber":167,"sourceCode":"        base_url: str,\n        auth_headers: dict[str, str],\n        client: AsyncHTTPHandler,\n    ) -> dict[str, Any]:\n        status = run_data.get(\"status\", \"\")\n        if status not in WatsonxOrchestrateTransformation.TERMINAL_STATES:\n            run_id: Final = run_data.get(\"run_id\") or run_data.get(\"id\") or \"\"\n            if not run_id:\n                raise ValueError(f\"WXO: No run_id in response: {run_data}\")\n            run_data = await WatsonxOrchestrateHandler._poll_run(\n                base_url=base_url,\n                run_id=run_id,\n                auth_headers=auth_headers,\n                client=client,\n            )\n            status = run_data.get(\"status\", \"\")\n\n        if status not in WatsonxOrchestrateTransformation.SUCCESS_STATES:\n            raise RuntimeError(f\"WXO run ended with non-success status '{status}': {run_data}\")\n\n        return run_data\n\n    @staticmethod\n    async def _accumulate_wxo_sse_text(response: Any) -> str:\n        accumulated_text = \"\"\n        async for line in response.aiter_lines():\n            if not line.startswith(\"data:\"):\n                continue\n            data_str = line[5:].strip()\n            if not data_str or data_str == \"[DONE]\":\n                continue\n            try:\n                event = json.loads(data_str)\n            except json.JSONDecodeError:\n                continue\n            chunk_text = WatsonxOrchestrateTransformation.extract_text_from_wxo_result(event)\n            if chunk_text:","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/a2a_protocol/providers/watsonx_orchestrate/handler.py#L149-L185","documentation":"Raised by the WXO handler after polling (or immediately) when the run's final status is not in SUCCESS_STATES. It means the watsonx Orchestrate run genuinely terminated in a failure state (or the status string is unrecognized, which also fails the membership check). The full run payload is included in the RuntimeError message for diagnosis.","triggerScenarios":"A WXO agent run that finishes with a failed/cancelled/error status (e.g. 'FAILED', 'CANCELLED', 'ERROR'), or a status string that LiteLLM's SUCCESS_STATES set does not recognize. Produced by any WXO agent call via LiteLLM where _poll_run returns a non-success terminal status.","commonSituations":"The underlying agent errored in watxsonx Orchestrate (bad input, agent misconfiguration, backend LLM failure); a WXO version introducing a new success status spelling that LiteLLM's SUCCESS_STATES doesn't include; user cancels the run in the WXO UI mid-poll.","solutions":["Inspect the run_data embedded in the exception message to identify the exact terminal status and any error details from watsonx Orchestrate.","Fix the root cause on the WXO side (agent config, prompt/input size, backend model availability), then retry the LiteLLM call.","If the status looks like a legitimate success variant missing from SUCCESS_STATES, update WatsonxOrchestrateTransformation.SUCCESS_STATES in the transformation class and report it upstream."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"def is_success_status(run_data: dict, success_states: set[str]) -> bool:\n    return run_data.get(\"status\", \"\") in success_states","tryCatchPattern":"terminal_statuses = {\"failed\", \"cancelled\", \"error\"}\nfor attempt in range(MAX_RETRIES):\n    try:\n        result = await wxo_call(...)\n        break\n    except RuntimeError as e:\n        msg = str(e)\n        if \"non-success status\" in msg and any(s in msg.lower() for s in terminal_statuses) and attempt < MAX_RETRIES - 1:\n            await asyncio.sleep(backoff)\n            continue\n        raise","preventionTips":["Validate agent inputs (size, formats) before sending to WXO to reduce failed runs.","Set a sensible poll timeout so cancelled/failed runs surface quickly instead of hanging.","Alert on the exact terminal status string in the exception to distinguish transient vs permanent failures."],"tags":["watsonx-orchestrate","a2a","run-failure","status"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}