The host writes genuinely useful refusals — "entry is owned by provider `x`,
update it through its reconcile" — and a dozen call sites threw them away. The
pattern was always one of two: a mutation whose `error` nothing rendered, or an
`await mutateAsync(...)` with no catch, which additionally produced an unhandled
rejection. Either way the operator clicked, nothing visible happened, and the
thing they asked for silently hadn't.
Fixed at each site, with the host's own message shown where there is one:
- Adding or editing a library entry kept the form open and said why, instead of
closing it as if it had saved and taking the typing with it. Deleting one
reports the refusal rather than leaving the card sitting there.
- The GPU preference, capture start/stop, recording delete and download, and the
dashboard's stop-session / request-keyframe / end-game all report failure. The
failed capture STOP is the one that mattered most: it is "stop & save", so a
swallowed error meant minutes of recording vanished with nothing on screen.
- The recordings Download had a comment claiming the detail view surfaces its
errors. It only does that for the selected row, and Download is on every row.
Two related fixes in the same area:
- `apiFetch` no longer navigates to /login synchronously from inside whichever
call noticed a 401 — very often a background poll the user never started.
Tearing the page down mid-render took unsaved editing state with it, which the
Displays page explicitly models. It defers a beat and coalesces, so a burst of
parallel 401s schedules one navigation.
- The plugin liveness probe treated the auth gate's 302 → /login → 200 HTML as a
healthy plugin, and rendered the console's own login page inside the plugin's
iframe. It also gave up permanently on the first failed probe, so the runner
restart at the end of every install threw away whatever was open in another
plugin. It rejects the redirect and keeps probing on a slower beat while down.
`apiErrorMessage` moves out of the display card into src/lib/errors.ts, since
half the console needs it now.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>