Safari: every click or keypress shows a `Cancelled` snackbar after opening Settings → MCP & APIs
Environment
- v2.41.0, self-hosted via the official Docker Compose (server, worker, postgres:16, redis)
- Safari, logged in
What happens
After visiting Settings → MCP & APIs, every subsequent click or keypress anywhere in the app pops a snackbar reading Cancelled in the bottom-right corner. It keeps happening for the life of the tab and stops as soon as the window is closed and reopened. Chrome and Firefox never show it. Nothing actually fails — the requests in question were cancelled deliberately.
Cause
Two things combine.
1. The rejection handler matches on the error name only. From the built bundle:
const a = r?.networkError?.name === "AbortError" || r?.name === "AbortError";
const s = r instanceof Error && isChunkLoadError(r);
!a && !s && enqueueToast(...) // raw error.message is shown here
WebKit does not name a cancelled request's rejection AbortError — it rejects with the message Cancelled and a different name — so the guard misses and the raw message reaches the user. Chromium names it AbortError, which is why this is Safari-only.
2. SettingsRestPlayground leaves a request in flight. The chunk creates an AbortController-backed fetch and has no cleanup path (no abort on unmount). Leaving the page leaves the request outstanding, and later interactions abort it — one snackbar per abort. That is why the page has to be visited once before the behaviour starts, and why a fresh tab is clean.
Suggested fix
In the rejection handler, detect aborts by something browser-independent — the AbortSignal's aborted flag, or DOMException with name === "AbortError" plus a message check — rather than the name alone. Separately, aborting the playground's controller on unmount would stop the rejections being generated at all.
Related
- #14780 added the
AbortErrorinterception this guard is based on. - #23571 fixed the same handler leaking a raw browser string on iOS Safari, but only for stale chunk-load errors.
Source: twentyhq/twenty