Skip to content

fix(tui): surface the real turn-failure detail, not just the code - #190

Merged
0xKT merged 1 commit into
mainfrom
fix/surface_turn_error_detail
Jul 23, 2026
Merged

0xKT merged 1 commit into
mainfrom
fix/surface_turn_error_detail

Conversation

@arelchan

Copy link
Copy Markdown
Contributor

Change description

Closes #114.

Every failed agent turn surfaces in the TUI as the same opaque line -- error: turn_failed (code=-32099) -- regardless of the real cause (a missing dependency, a provider error, a Node version problem, ...). That made #119 (missing orjson) impossible to diagnose from the UI and forced a from-scratch reproduction.

Root cause: TurnFailed already carries the underlying error (error=str(exc) in the scheduler), but the spine sink discarded it -- raven/tui_rpc/spine.py called emit_error(..., "turn_failed", "internal") with the detail hardcoded, so TurnFailed.error never reached the wire or the UI.

Fix

Thread the failure detail end to end:

  • ui-tui/rpc-schema/openrpc.json: add an optional detail string to the ErrorEvent payload (single source of truth).
  • ui-tui/src/rpc/generated.ts: regenerated from the schema (npm run lint:rpc confirms it is in sync).
  • raven/tui_rpc/models.py: add detail: str | None = None to ErrorEventPayload.
  • raven/tui_rpc/spine.py: emit_error accepts an optional detail and includes it only when non-empty; the TurnFailed sink passes event.error.
  • ui-tui/src/app/chatStream.ts: onError appends the first line of detail (capped) to the error line, so the user sees e.g. error: turn_failed (code=-32099): No module named 'orjson'.

code / message / reason are unchanged, so the cancelled_by_client path and existing consumers are unaffected; detail is omitted when empty (back-compat).

Tests

  • tests/test_tui_rpc_spine.py: emit_error with a detail includes it in the payload; the existing no-detail test still asserts it is omitted.
  • ui-tui/src/__tests__/chatStream.test.ts: an error event carrying detail renders error: turn_failed (code=-32099): <detail>.

Type of change

  • Bug fix
  • New feature
  • Document
  • Others

Checklists

Development

  • Lint rules pass locally (ruff, eslint, prettier, tsc, lint:rpc)
  • Application changes have been tested thoroughly
  • Automated tests covering modified code pass (python spine + tui chatStream + full npm test)

Code review

  • Pull request has a descriptive title and context useful to a reviewer

TurnFailed carries the underlying error (error=str(exc)), but the spine
sink dropped it: emit_error was called with a hardcoded turn_failed /
internal, so every failed turn -- missing dependency, provider error,
node issue -- collapsed to the same opaque 'error: turn_failed
(code=-32099)' with no way to tell them apart.

Thread the failure detail through: add an optional detail field to the
error event payload (openrpc schema + regenerated types + pydantic
model), pass TurnFailed.error into emit_error, and append the first line
of it to the tui error line. reason/code/message stay unchanged, so the
cancelled-by-client path and existing consumers are unaffected.

Closes #114

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@0xKT
0xKT self-requested a review July 23, 2026 06:59
@0xKT
0xKT merged commit afea793 into main Jul 23, 2026
8 checks passed
@0xKT
0xKT deleted the fix/surface_turn_error_detail branch July 23, 2026 07:00
@0xKT 0xKT mentioned this pull request Jul 23, 2026
6 of 12 tasks
0xKT added a commit that referenced this pull request Jul 23, 2026
## Summary

Bump the package version from 0.1.8 to 0.1.9 (patch release). All five
PRs merged since v0.1.8 are fixes, no new features:

- #204 fix: add configurable llm_call_timeout to bound stalled LLM calls
- #199 fix(cli): make onboard readable on light-background terminals
- #189 fix(cli): pick the first node >= 22 across all PATH entries
- #196 fix(commitlint): unify commit/PR length to header-max-length
- #190 fix(tui): surface the real turn-failure detail, not just the code

## Type

- [ ] Fix
- [ ] Feature
- [ ] Docs
- [ ] CI / tooling
- [ ] Refactor
- [x] Other

## Verification

- [x] Relevant tests pass locally
- [x] Relevant lint / type checks pass locally
- [ ] User-facing docs or screenshots are updated when needed

Bump is limited to `pyproject.toml` and `uv.lock` (`uv lock` sync).
Commit message lint passes locally.

## Risk

- [x] Security impact considered
- [x] Backward compatibility considered
- [x] Rollback path is clear for risky changes

Version-only change; no code or behavior change.

## Related Issues

N/A

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
KevinHuSh pushed a commit to KevinHuSh/Raven that referenced this pull request Sep 14, 2026
…erMind-AI#190)

## Change description

Closes EverMind-AI#114.

Every failed agent turn surfaces in the TUI as the same opaque line --
`error: turn_failed (code=-32099)` -- regardless of the real cause (a
missing dependency, a provider error, a Node version problem, ...). That
made EverMind-AI#119 (missing `orjson`) impossible to diagnose from the UI and
forced a from-scratch reproduction.

Root cause: `TurnFailed` already carries the underlying error
(`error=str(exc)` in the scheduler), but the spine sink discarded it --
`raven/tui_rpc/spine.py` called `emit_error(..., "turn_failed",
"internal")` with the detail hardcoded, so `TurnFailed.error` never
reached the wire or the UI.

## Fix

Thread the failure detail end to end:
- `ui-tui/rpc-schema/openrpc.json`: add an optional `detail` string to
the `ErrorEvent` payload (single source of truth).
- `ui-tui/src/rpc/generated.ts`: regenerated from the schema (`npm run
lint:rpc` confirms it is in sync).
- `raven/tui_rpc/models.py`: add `detail: str | None = None` to
`ErrorEventPayload`.
- `raven/tui_rpc/spine.py`: `emit_error` accepts an optional `detail`
and includes it only when non-empty; the `TurnFailed` sink passes
`event.error`.
- `ui-tui/src/app/chatStream.ts`: `onError` appends the first line of
`detail` (capped) to the error line, so the user sees e.g. `error:
turn_failed (code=-32099): No module named 'orjson'`.

`code` / `message` / `reason` are unchanged, so the
`cancelled_by_client` path and existing consumers are unaffected;
`detail` is omitted when empty (back-compat).

## Tests

- `tests/test_tui_rpc_spine.py`: `emit_error` with a detail includes it
in the payload; the existing no-detail test still asserts it is omitted.
- `ui-tui/src/__tests__/chatStream.test.ts`: an error event carrying
`detail` renders `error: turn_failed (code=-32099): <detail>`.

## Type of change
- [x] Bug fix
- [ ] New feature
- [ ] Document
- [ ] Others

## Checklists

### Development
- [x] Lint rules pass locally (ruff, eslint, prettier, tsc, lint:rpc)
- [x] Application changes have been tested thoroughly
- [x] Automated tests covering modified code pass (python spine + tui
chatStream + full `npm test`)

### Code review
- [x] Pull request has a descriptive title and context useful to a
reviewer

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
KevinHuSh pushed a commit to KevinHuSh/Raven that referenced this pull request Sep 14, 2026
## Summary

Bump the package version from 0.1.8 to 0.1.9 (patch release). All five
PRs merged since v0.1.8 are fixes, no new features:

- EverMind-AI#204 fix: add configurable llm_call_timeout to bound stalled LLM calls
- EverMind-AI#199 fix(cli): make onboard readable on light-background terminals
- EverMind-AI#189 fix(cli): pick the first node >= 22 across all PATH entries
- EverMind-AI#196 fix(commitlint): unify commit/PR length to header-max-length
- EverMind-AI#190 fix(tui): surface the real turn-failure detail, not just the code

## Type

- [ ] Fix
- [ ] Feature
- [ ] Docs
- [ ] CI / tooling
- [ ] Refactor
- [x] Other

## Verification

- [x] Relevant tests pass locally
- [x] Relevant lint / type checks pass locally
- [ ] User-facing docs or screenshots are updated when needed

Bump is limited to `pyproject.toml` and `uv.lock` (`uv lock` sync).
Commit message lint passes locally.

## Risk

- [x] Security impact considered
- [x] Backward compatibility considered
- [x] Rollback path is clear for risky changes

Version-only change; no code or behavior change.

## Related Issues

N/A

Co-authored-by: Claude (claude-opus-4-8) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TUI sink discards actual error message in TurnFailed — user sees useless generic 'turn_failed (code=-32099)'

2 participants