Commit graph

1 commit

Author SHA1 Message Date
Andre Kurait
5113976a69
fix(run_agent): surface traceback frame for empty-message errors in 📝 Error:
## Problem

When the retry loop's `_summarize_api_error()` receives an exception
with an empty `str(error)` (bare `raise AssertionError()`, bare `raise`
without args, or third-party SDK accumulators that discard the original
payload), users see:

    📝 Error:

...with nothing after the colon, and no way to diagnose the root cause
without re-running under a debugger.

## Real-world trigger

The anthropic SDK's streaming accumulator raises:

    RuntimeError('Unexpected event order, got error before "message_start"')

when Bedrock or Anthropic returns a service-level `error` event as the
first stream event (throttling, overload, 5xx, etc.).  The SDK has the
error payload in hand but throws it away before raising — all the user
sees is the cryptic "event order" message with zero context.  Even
worse, bare `AssertionError()`s in user-authored code paths often have
empty messages entirely.

## Fix

When the error's string representation is empty or whitespace-only,
walk `error.__traceback__` and format the last frame as:

    AssertionError at /path/file.py:123 in some_method() — source line

This gives users an actionable locator without changing the output for
any error with a real message.

## Changes

- `run_agent.py` — `_summarize_api_error()`: added empty-payload guard
  at the top of the function before the existing Cloudflare-HTML path.
- `tests/agent/test_summarize_api_error.py` — 4 new tests covering
  empty AssertionError, empty-message RuntimeError without traceback,
  whitespace-only message, and the fall-through path (non-empty errors
  must not be affected).

## Tests

    pytest tests/agent/test_summarize_api_error.py -v
    # 4 passed in 4.88s

## Risk

- Zero impact on any error with a non-empty message — the new branch
  only fires when `str(error).strip()` is falsy.
- `traceback` is a stdlib module; import is lazy (inside the branch).
- `getattr(error, "__traceback__", None)` is the documented API and
  handles manually-constructed exceptions that were never raised.

Signed-off-by: Andre Kurait <andrekurait@gmail.com>
2026-04-23 20:56:42 +00:00