Improve unhandled exception handling

This commit is contained in:
Andrey Antukh 2026-01-27 13:02:53 +01:00 committed by Andrés Moya
parent bd2ef8057e
commit 61969f3eb5
5 changed files with 43 additions and 6 deletions

View File

@ -29,6 +29,9 @@
;; Will contain the latest error report assigned ;; Will contain the latest error report assigned
(def last-report nil) (def last-report nil)
;; Will contain last uncaught exception
(def last-exception nil)
(defn- print-data! (defn- print-data!
[data] [data]
(-> data (-> data
@ -338,7 +341,6 @@
(print-data! werror) (print-data! werror)
(print-explain! werror)))))))) (print-explain! werror))))))))
(defonce uncaught-error-handler (defonce uncaught-error-handler
(letfn [(is-ignorable-exception? [cause] (letfn [(is-ignorable-exception? [cause]
(let [message (ex-message cause)] (let [message (ex-message cause)]
@ -349,10 +351,31 @@
(on-unhandled-error [event] (on-unhandled-error [event]
(.preventDefault ^js event) (.preventDefault ^js event)
(when-let [error (unchecked-get event "error")] (when-let [cause (unchecked-get event "error")]
(when-not (is-ignorable-exception? error) (set! last-exception cause)
(on-error error))))] (when-not (is-ignorable-exception? cause)
(ex/print-throwable cause :prefix "uncaught exception")
(st/async-emit!
(ntf/show {:content (tr "errors.unexpected-exception" (ex-message cause))
:type :toast
:level :error
:timeout 3000})))))
(on-unhandled-rejection [event]
(.preventDefault ^js event)
(when-let [cause (unchecked-get event "reason")]
(set! last-exception cause)
(ex/print-throwable cause :prefix "uncaught rejection")
(st/async-emit!
(ntf/show {:content (tr "errors.unexpected-exception" (ex-message cause))
:type :toast
:level :error
:timeout 3000}))))]
(.addEventListener glob/window "error" on-unhandled-error) (.addEventListener glob/window "error" on-unhandled-error)
(.addEventListener glob/window "unhandledrejection" on-unhandled-rejection)
(fn [] (fn []
(.removeEventListener glob/window "error" on-unhandled-error)))) (.removeEventListener glob/window "error" on-unhandled-error)
(.removeEventListener glob/window "unhandledrejection" on-unhandled-rejection))))

View File

@ -8,6 +8,7 @@
"React error boundary components" "React error boundary components"
(:require (:require
["react-error-boundary" :as reb] ["react-error-boundary" :as reb]
[app.common.exceptions :as ex]
[app.main.errors :as errors] [app.main.errors :as errors]
[app.main.refs :as refs] [app.main.refs :as refs]
[goog.functions :as gfn] [goog.functions :as gfn]
@ -34,7 +35,8 @@
;; very small amount of time, so we debounce for 100ms for ;; very small amount of time, so we debounce for 100ms for
;; avoid duplicate and redundant reports ;; avoid duplicate and redundant reports
(gfn/debounce (fn [error info] (gfn/debounce (fn [error info]
(js/console.log "Cause stack: \n" (.-stack error)) (set! errors/last-exception error)
(ex/print-throwable error)
(js/console.error (js/console.error
"Component trace: \n" "Component trace: \n"
(unchecked-get info "componentStack") (unchecked-get info "componentStack")

View File

@ -8,6 +8,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.exceptions :as ex]
[app.common.files.repair :as cfr] [app.common.files.repair :as cfr]
[app.common.files.validate :as cfv] [app.common.files.validate :as cfv]
[app.common.json :as json] [app.common.json :as json]
@ -456,3 +457,8 @@
(defn ^:export network-averages (defn ^:export network-averages
[] []
(.log js/console (clj->js @http/network-averages))) (.log js/console (clj->js @http/network-averages)))
(defn print-last-exception
[]
(some-> errors/last-exception ex/print-throwable))

View File

@ -1466,6 +1466,9 @@ msgstr ""
msgid "errors.generic" msgid "errors.generic"
msgstr "Something wrong has happened." msgstr "Something wrong has happened."
msgid "errors.unexpected-exception"
msgstr "Unexpected exception: %s"
#: src/app/main/errors.cljs:200 #: src/app/main/errors.cljs:200
msgid "errors.internal-assertion-error" msgid "errors.internal-assertion-error"
msgstr "Internal Assertion Error" msgstr "Internal Assertion Error"

View File

@ -1462,6 +1462,9 @@ msgstr ""
msgid "errors.generic" msgid "errors.generic"
msgstr "Ha ocurrido algún error." msgstr "Ha ocurrido algún error."
msgid "errors.unexpected-exception"
msgstr "Error inesperado: %s"
#: src/app/main/errors.cljs:200 #: src/app/main/errors.cljs:200
msgid "errors.internal-assertion-error" msgid "errors.internal-assertion-error"
msgstr "Error interno de aserción" msgstr "Error interno de aserción"