Run failure events and auth error handling fixes
Cluster 15561 · gateway. Data as of
3 open items. Fix merged in #19706. Check it covers your case.
The short answer
- Known?
- Yes. 7 related items grouped here, 1 issue already closed.
- Fix event
- A fix was merged to main in PR #19706. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
unresolved. That is separate from the fix event. - Still open
- 1 issue and 2 PRs.
Next step: read #19706, then check whether your report is one of the 1 still open.
Read #19706Pick up a Lab task
Multiple fixes addressing incorrect or missing run.failed event emission, particularly for authentication errors and non-retryable client failures in the gateway and API server. Changes ensure runs with errors are properly marked and reported rather than silently misclassified.
Open issues1
- Issue#57899Provider auth errors should be retryable (failed, not delivered)
Open PRs2
Fixes on record
-
#19706 fix(api_server): emit run.failed when run_conversation returns failed=True
files:
gateway/platforms/api_server.pyShow the diff
-
gateway/platforms/api_server.py@@ -2578,21 +2578,39 @@ def _run_sync(): return r, u result, usage = await asyncio.get_running_loop().run_in_executor(None, _run_sync) - final_response = result.get("final_response", "") if isinstance(result, dict) else "" - q.put_nowait({ - "event": "run.completed", - "run_id": run_id, - "timestamp": time.time(), - "output": final_response, - "usage": usage, - }) - self._set_run_status( - run_id, - "completed", - output=final_response, - usage=usage, - last_event="run.completed", - ) + # Check for structured failure (non-retryable client errors like + # 401/400 return failed=True instead of raising, so the except + # block below never fires — issue #15561). + if isinstance(result, dict) and result.get("failed"): + error_msg = result.get("error") or "agent run failed" + q.put_nowait({ + "event": "run.failed", + "run_id": run_id, + "timestamp": time.time(), + "error": error_msg, + }) + self._set_run_status( + run_id, + "failed", + error=error_msg, + last_event="run.failed", + ) + else: + final_response = result.get("final_response", "") if isinstance(result, dict) else "" + q.put_nowait({ + "event": "run.completed", + "run_id": run_id, + "timestamp": time.time(), + "output": final_response, + "usage": usage, + }) + self._set_run_status( + run_id, + "completed", + output=final_response, + usage=usage, + last_event="run.completed", + ) except asyncio.CancelledError: self._set_run_status( run_id,
-
2 PRs closed without merging
From the close comments: merged via another change 1 · superseded by another PR 1
Closed issues · 1
- Closed#15561Gateway emits run.completed for runs that failed with a non-retryable client error (no run.failed)
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.26: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- gateway
- Merged PRs
- #19706
- Closed issues
- 1
- Attempts
- 2 PRs closed without merging
- Fix link checked
- 4 May 2026