diff --git a/frontend/src/app/main/errors.cljs b/frontend/src/app/main/errors.cljs index 63e33e4aff..745f1adec7 100644 --- a/frontend/src/app/main/errors.cljs +++ b/frontend/src/app/main/errors.cljs @@ -355,10 +355,11 @@ (= message "Unexpected end of input") (str/starts-with? message "invalid props on component") (str/starts-with? message "Unexpected token ") - ;; Abort errors are expected when an in-flight HTTP request is - ;; cancelled (e.g. via RxJS unsubscription / take-until). They - ;; are handled gracefully inside app.util.http/fetch and must - ;; NOT be surfaced as application errors. + ;; Native AbortError DOMException: raised when an in-flight + ;; HTTP fetch is cancelled via AbortController (e.g. by an + ;; RxJS unsubscription / take-until chain). These are + ;; handled gracefully inside app.util.http/fetch and must NOT + ;; be surfaced as application errors. (= (.-name ^js cause) "AbortError")))) (on-unhandled-error [event] diff --git a/frontend/src/app/util/http.cljs b/frontend/src/app/util/http.cljs index 34971caaef..ae8237a943 100644 --- a/frontend/src/app/util/http.cljs +++ b/frontend/src/app/util/http.cljs @@ -127,11 +127,17 @@ (fn [] (vreset! unsubscribed? true) (when @abortable? - ;; Provide an explicit reason so that the resulting AbortError carries - ;; a meaningful message instead of the browser default - ;; "signal is aborted without reason". - (.abort ^js controller (ex-info (str "fetch to '" uri "' is aborted") - {:uri uri})))))))) + ;; Do NOT pass a custom reason to .abort(): browsers that support + ;; AbortController reason (Chrome 98+, Firefox 97+) would reject + ;; the fetch promise with the supplied value directly. When that + ;; value is a ClojureScript ExceptionInfo its `.name` property is + ;; "Error", not "AbortError", which defeats every existing guard + ;; that checks `(= (.-name cause) "AbortError")`. Calling .abort + ;; without a reason always produces a native DOMException whose + ;; `.name` is "AbortError", which is correctly recognised and + ;; suppressed by both the p/catch handler and the global + ;; unhandled-exception filter. + (.abort ^js controller))))))) (defn response->map [response]