Improve unhandled exception handling

This commit is contained in:
Andrey Antukh
2026-01-27 13:02:53 +01:00
parent 5036561751
commit c883ff6794
5 changed files with 43 additions and 6 deletions

View File

@@ -29,6 +29,9 @@
;; Will contain the latest error report assigned
(def last-report nil)
;; Will contain last uncaught exception
(def last-exception nil)
(defn- print-data!
[data]
(-> data
@@ -338,7 +341,6 @@
(print-data! werror)
(print-explain! werror))))))))
(defonce uncaught-error-handler
(letfn [(is-ignorable-exception? [cause]
(let [message (ex-message cause)]
@@ -349,10 +351,31 @@
(on-unhandled-error [event]
(.preventDefault ^js event)
(when-let [error (unchecked-get event "error")]
(when-not (is-ignorable-exception? error)
(on-error error))))]
(when-let [cause (unchecked-get event "error")]
(set! last-exception cause)
(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 "unhandledrejection" on-unhandled-rejection)
(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"
(:require
["react-error-boundary" :as reb]
[app.common.exceptions :as ex]
[app.main.errors :as errors]
[app.main.refs :as refs]
[goog.functions :as gfn]
@@ -34,7 +35,8 @@
;; very small amount of time, so we debounce for 100ms for
;; avoid duplicate and redundant reports
(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
"Component trace: \n"
(unchecked-get info "componentStack")

View File

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

View File

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

View File

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