diff --git a/backend/src/app/http/errors.clj b/backend/src/app/http/errors.clj index 2445e6099..875bd5663 100644 --- a/backend/src/app/http/errors.clj +++ b/backend/src/app/http/errors.clj @@ -88,11 +88,19 @@ (= code :params-validation) (let [explain (::sm/explain data) - payload (sm/humanize-data explain)] + explain (sm/humanize-data explain)] {::yrs/status 400 ::yrs/body (-> data (dissoc ::sm/explain) - (assoc :data payload))}) + (assoc :explain explain))}) + + (= code :data-validation) + (let [explain (::sm/explain data) + explain (sm/humanize-data explain)] + {::yrs/status 400 + ::yrs/body (-> data + (dissoc ::sm/explain) + (assoc :explain explain))}) (= code :request-body-too-large) {::yrs/status 413 ::yrs/body data} @@ -114,18 +122,18 @@ (cond (= code :data-validation) (let [explain (::sm/explain data) - payload (sm/humanize-data explain)] - (l/error :hint "data assertion error" :message (ex-message error) :cause cause) + explain (sm/humanize-data explain)] + (l/error :hint "data assertion error" :cause cause) {::yrs/status 500 ::yrs/body {:type :server-error :code :assertion :data (-> data (dissoc ::sm/explain) - (assoc :data payload))}}) + (assoc :explain explain))}}) (= code :spec-validation) (let [explain (ex/explain data)] - (l/error :hint "spec assertion error" :message (ex-message error) :cause cause) + (l/error :hint "spec assertion error" :cause cause) {::yrs/status 500 ::yrs/body {:type :server-error :code :assertion @@ -135,7 +143,7 @@ :else (do - (l/error :hint "assertion error" :message (ex-message error) :cause cause) + (l/error :hint "assertion error" :cause cause) {::yrs/status 500 ::yrs/body {:type :server-error :code :assertion @@ -150,7 +158,7 @@ [error request parent-cause] (binding [l/*context* (request->context request)] (let [cause (or parent-cause error)] - (l/error :hint "internal error" :message (ex-message error) :cause cause) + (l/error :hint "internal error" :cause cause) {::yrs/status 500 ::yrs/body {:type :server-error :code :unhandled @@ -175,7 +183,7 @@ (let [state (.getSQLState ^java.sql.SQLException error) cause (or parent-cause error)] (binding [l/*context* (request->context request)] - (l/error :hint "PSQL error" :message (ex-message error) + (l/error :hint "PSQL error" :cause cause) (cond (= state "57014") @@ -205,7 +213,7 @@ ;; This means that exception is not a controlled exception. (nil? edata) (binding [l/*context* (request->context request)] - (l/error :hint "unexpected error" :message (ex-message error) :cause cause) + (l/error :hint "unexpected error" :cause cause) {::yrs/status 500 ::yrs/body {:type :server-error :code :unexpected @@ -213,7 +221,7 @@ :else (binding [l/*context* (request->context request)] - (l/error :hint "unhandled error" :message (ex-message error) :cause cause) + (l/error :hint "unhandled error" :cause cause) {::yrs/status 500 ::yrs/body {:type :server-error :code :unhandled diff --git a/backend/src/app/rpc/commands/binfile.clj b/backend/src/app/rpc/commands/binfile.clj index 1b11c8ab4..d9db769fa 100644 --- a/backend/src/app/rpc/commands/binfile.clj +++ b/backend/src/app/rpc/commands/binfile.clj @@ -973,7 +973,6 @@ :import-id id :elapsed (dt/format-duration (tp)) :error? (some? @cs) - :cause @cs ))))) ;; --- Command: export-binfile diff --git a/common/src/app/common/exceptions.cljc b/common/src/app/common/exceptions.cljc index 0f56082f7..cb6388997 100644 --- a/common/src/app/common/exceptions.cljc +++ b/common/src/app/common/exceptions.cljc @@ -66,9 +66,9 @@ (defn explain ([data] (explain data nil)) - ([data {:keys [level length] :or {level 8 length 10} :as opts}] + ([data {:keys [level length] :or {level 8 length 12} :as opts}] (cond - ;; ;; NOTE: a special case for spec validation errors on integrant + ;; NOTE: a special case for spec validation errors on integrant (and (= (:reason data) :integrant.core/build-failed-spec) (contains? data :explain)) (explain (:explain data) opts) @@ -81,8 +81,7 @@ (s/explain-out (update data ::s/problems #(take length %))))) (contains? data ::sm/explain) - (-> (sm/humanize-data (::sm/explain data)) - (pp/pprint-str {:level level :length length}))))) + (sm/humanize-data (::sm/explain data) :level level :length length)))) #?(:clj (defn format-throwable diff --git a/common/src/app/common/logging.cljc b/common/src/app/common/logging.cljc index 0402343b9..89a929d0b 100644 --- a/common/src/app/common/logging.cljc +++ b/common/src/app/common/logging.cljc @@ -271,7 +271,7 @@ (js/console.error n (pr-str v)) (js/console.error n v)))) - (when cause + (when (ex/exception? cause) (let [data (ex-data cause) explain (ex/explain data)] (when explain diff --git a/common/src/app/common/schema.cljc b/common/src/app/common/schema.cljc index 641837f53..82aca3ffe 100644 --- a/common/src/app/common/schema.cljc +++ b/common/src/app/common/schema.cljc @@ -8,7 +8,9 @@ (:refer-clojure :exclude [deref merge parse-uuid]) #?(:cljs (:require-macros [app.common.schema :refer [ignoring]])) (:require + [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.pprint :as pp] [app.common.schema.generators :as sg] [app.common.schema.openapi :as-alias oapi] [app.common.schema.registry :as sr] @@ -142,10 +144,19 @@ (m/decoder s options transformer))) (defn humanize-data - [explain-data] - (-> explain-data - (update :schema form) - (update :errors (fn [errors] (map #(update % :schema form) errors))))) + [{:keys [schema errors value]} & {:keys [length level]}] + (let [errors (mapv #(update % :schema form) errors)] + (with-out-str + (println "Schema: ") + (println (pp/pprint-str (form schema)) {:level (d/nilv level 10) + :length (d/nilv length 10)}) + (println) + (println "Errors:") + (println (pp/pprint-str errors {:level (d/nilv level 10) + :length (d/nilv length 10)})) + (println "Value:") + (println (pp/pprint-str value {:level (d/nilv level 5) + :length (d/nilv length 10)}))))) (defn pretty-explain [s d] @@ -191,7 +202,7 @@ (fn [v] (let [result (v-fn v)] (when (and (not result) (true? dm/*assert-context*)) - (let [hint (str "schema assert: " (pr-str (form s))) + (let [hint "schema validation" exp (e-fn v)] (throw (ex-info hint {:type :assertion :code :data-validation @@ -204,7 +215,7 @@ [s v] (let [result (validate s v)] (when (and (not result) (true? dm/*assert-context*)) - (let [hint (str "schema assert: " (pr-str (form s))) + (let [hint "schema validation" exp (explain s v)] (throw (ex-info hint {:type :assertion :code :data-validation diff --git a/frontend/src/app/main/errors.cljs b/frontend/src/app/main/errors.cljs index c7e83c3b3..a17b5bada 100644 --- a/frontend/src/app/main/errors.cljs +++ b/frontend/src/app/main/errors.cljs @@ -25,7 +25,7 @@ [data] (-> data (dissoc ::sm/explain) - (dissoc :hint) + (dissoc :explain) (dissoc ::trace) (dissoc ::instance) (pp/pprint {:width 70}))) @@ -33,8 +33,9 @@ (defn- print-explain! [data] (when-let [explain (::sm/explain data)] - (-> (sm/humanize-data explain) - (pp/pprint {:width 70})))) + (js/console.log (sm/humanize-data explain))) + (when-let [explain (:explain data)] + (js/console.log explain))) (defn- print-trace! [data] @@ -98,7 +99,8 @@ (print-group! "Validation Error" (fn [] - (print-data! error)))) + (print-data! error) + (print-explain! error)))) ;; This is a pure frontend error that can be caused by an active @@ -223,7 +225,22 @@ (print-group! "Server Error" (fn [] - (print-data! error)))) + (print-data! (dissoc error :data)) + + (when-let [werror (:data error)] + (cond + (= :assertion (:type werror)) + (print-group! "Assertion Error" + (fn [] + (print-data! werror) + (print-explain! werror))) + + :else + (print-group! "Unexpected" + (fn [] + (print-data! werror) + (print-explain! werror)))))))) + (defonce uncaught-error-handler (letfn [(is-ignorable-exception? [cause] diff --git a/frontend/src/app/main/ui/dashboard/import.cljs b/frontend/src/app/main/ui/dashboard/import.cljs index 120119193..4edb59bf6 100644 --- a/frontend/src/app/main/ui/dashboard/import.cljs +++ b/frontend/src/app/main/ui/dashboard/import.cljs @@ -258,9 +258,9 @@ {:cmd :analyze-import :files files}) (rx/delay-emit emit-delay) + (rx/filter some?) (rx/subs (fn [{:keys [uri data error type] :as msg}] - (log/debug :uri uri :data data :error error) (if (some? error) (swap! state update :files set-analyze-error uri) (swap! state update :files set-analyze-result uri type data)))))))