Skip to content

fix: surface API errors (rate limits, failures) in the app UIs - #2

Open
erhnysr wants to merge 1 commit into
RitualChain:mainfrom
erhnysr:fix/surface-api-errors
Open

fix: surface API errors (rate limits, failures) in the app UIs#2
erhnysr wants to merge 1 commit into
RitualChain:mainfrom
erhnysr:fix/surface-api-errors

Conversation

@erhnysr

@erhnysr erhnysr commented Jul 25, 2026

Copy link
Copy Markdown

What this fixes

The Terminal, Calendar, and Notes apps each call /api/agent/generate and immediately read the body without checking the HTTP status:

const response = await fetch("/api/agent/generate", { ... })
const { text } = await response.json()

When the response isn't OK, text is undefined and the app misbehaves:

  • Terminal / Calendar — fall into their catch and show a generic "error processing your request" message.
  • Notes — swallows the error entirely (catch {}), so categorization just silently does nothing.

The most visible casualty is the rate limiter: middleware.ts returns a helpful 429 body — { "error": "Too many requests", "message": "Please slow down. Try again in a minute." } — but because no app checks response.ok, that message never reaches the user. A documented, headlined feature is effectively invisible.

The fix

Check response.ok in all three apps before parsing. On a non-OK response, read the server's message/error and throw it, then surface it in each app's existing error path:

if (!response.ok) {
  const errorBody = await response.json().catch(() => null)
  throw new Error(
    errorBody?.message || errorBody?.error || `Request failed (${response.status})`,
  )
}
  • Terminal — includes the message in its fallback line (Agent error: <message> Falling back to direct execution.).
  • Calendar — shows the message in its assistant error bubble.
  • Notes — previously silent; adds a small inline error (styled with the existing destructive design token) so failures are visible.

The generic strings are kept as fallbacks when no server message is present.

Verification (local)

Dev server up, then 21 rapid POST /api/agent/generate calls to trip the middleware:

Request #21 -> HTTP 429
Body: {"error":"Too many requests","message":"Please slow down. Try again in a minute."}

The apps now read errorBody.message and display "Please slow down. Try again in a minute." instead of a generic error (or, for Notes, instead of nothing). The 500 path ({ "error": "An error occurred processing your request" }) is covered by the errorBody?.error fallback.

Also verified:

  • bunx tsc --noEmit — clean
  • bun run build — compiles successfully

Before / after — Notes app

The Notes "AI Categorize All" action, run while the backend is returning the middleware's 429. Before, the failure is swallowed silently (no feedback); after, the server's message is surfaced inline.

Before (silent failure) After (error surfaced)
before after

After shows the banner "Categorization failed: Please slow down. Try again in a minute." — the exact message from middleware.ts, which previously never reached the user. (Terminal and Calendar surface the same message in their existing error UI.)

Scope

Three UI files. Same small response.ok guard in each; Notes additionally gets one useState and a small inline error element since it had no error surface at all. No API/route/middleware changes.

The Terminal, Calendar, and Notes apps called /api/agent/generate and read
`const { text } = await response.json()` without checking response.ok. On a
non-OK response (e.g. the middleware's 429 rate limit, or a 500) `text` was
undefined: Terminal/Calendar showed a generic message and Notes failed
silently, so the rate limiter's "Please slow down" message never reached users.

Check response.ok in all three, throw the server's message/error, and surface
it: Terminal in its fallback line, Calendar in its error bubble, and Notes via
a new inline error (previously it swallowed errors with no UI).
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

@erhnysr is attempting to deploy a commit to the 0xBuns Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant