Files
twenty/packages
Félix Malfait a505ed3245 feat(ai): typed CONTEXT_WINDOW_EXCEEDED error that hides the pointless Retry (#22488)
## Rationale

When message pruning can't fit the conversation into the model's context
window, `chat-execution.service.ts` throws a **raw `Error`**.
`mapErrorToStreamError` classifies it as generic
`STREAM_EXECUTION_FAILED`, so the client renders a standard failure with
a **Retry button that deterministically fails again** — the conversation
doesn't get shorter by retrying. Users loop on Retry against a
permanently-failing thread.

## Why this is the root cause, not a symptom patch

The failure is *terminal for the thread by construction*, and the error
channel already distinguishes terminal-vs-retryable via typed
`AiExceptionCode`s — this failure just never got one. Adding
`CONTEXT_WINDOW_EXCEEDED` (typed exception → `UserInputError` mapping
instead of a 500 → both error surfaces render the start-a-new-thread
message without `onRetry`) puts it on the same rails as
`API_KEY_NOT_CONFIGURED` and the other special-cased codes. Both
frontend error surfaces route through `AiChatErrorRenderer`, so one case
covers the in-message and under-list renderings.

The deeper endgame (auto-summarize/compact older turns so threads never
brick) is a multi-week feature — and this typed error remains necessary
even then, as its terminal fallback.

## User impact

Instead of an opaque error and a Retry that never works, users hitting
the context limit get told exactly what happened and what to do (start a
new thread), and monitoring stops counting a user-condition as a server
error.

## Test plan

- [ ] CI green
- [ ] Manual: fill a thread past the model limit → typed message, no
Retry on either error surface

https://claude.ai/code/session_01Lyi6zTema2FMVVh8MD6c38

---
_Generated by [Claude
Code](https://claude.ai/code/session_01Lyi6zTema2FMVVh8MD6c38)_

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22488?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-02 21:26:41 +02:00
..