NousResearch/hermes-agent

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

1open issue
2open PRs
7items grouped
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.

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

  • PR#57910fix(gateway): mark proxy failures as failed runs
  • PR#57975fix: add failed flag to provider auth error response (#57899)

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #19706 fix(api_server): emit run.failed when run_conversation returns failed=True

    merged to main

    files: gateway/platforms/api_server.py

    Show 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

  • #15564 fix(api_server): emit run.failed when run_conversation returns failed=True · merged via another change → #19706
  • #97136 fix(gateway): mark provider auth resolution failures failed · superseded by another PR → #57975, #57899
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.00 means 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 Lab

At a glance

Subsystem
gateway
Merged PRs
#19706
Closed issues
1
Attempts
2 PRs closed without merging
Fix link checked
4 May 2026

For your agent

The same facts, typed.