This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-10-18
Channels
- # announcements (12)
- # babashka (6)
- # beginners (62)
- # calva (3)
- # cider (41)
- # clerk (5)
- # clojure (192)
- # clojure-bay-area (1)
- # clojure-europe (14)
- # clojure-norway (97)
- # clojure-uk (6)
- # clojuredesign-podcast (4)
- # clojurescript (30)
- # code-reviews (7)
- # cursive (32)
- # datahike (4)
- # datomic (35)
- # docker (8)
- # emacs (8)
- # events (1)
- # fulcro (13)
- # helix (19)
- # hoplon (4)
- # hyperfiddle (37)
- # jobs-discuss (10)
- # membrane (11)
- # missionary (19)
- # off-topic (28)
- # polylith (8)
- # portal (10)
- # practicalli (8)
- # re-frame (31)
- # reitit (6)
- # shadow-cljs (39)
- # timbre (3)
- # vim (1)
- # xtdb (6)
Hello everyone 👋 How does the REPL pass\handle exceptions over evaluated expressions? I ask because I encountered an unexpected behavior when I wrapped an exception with more info along the chain but when I evaluate an expression I still seem to get only the inner most exception. for illustration of the gap:
(-> my-obj
-resolve)
=>
:repl/exception!
;
; Execution error (Error) at (<cljs repl>:1).
; No protocol method ILookup.-lookup defined for type null:
(try (-> my-obj
-resolve)
(catch js/Object e
e))
=>
#error {:message "My Exception"
:cause #object[Error Error: No protocol method ILookup.-lookup defined for type null: ]}
not sure if it's relevant but I construct and throw my exception using (throw (ex-info...))
kinda hard to answer, as this doesn't show anything about the code actually throwing the exception.
each repl eval has an implicit try/catch, so the first one the REPL eval is printing the caught exception
> each repl eval has an implicit try/catch, so the first one the REPL eval is printing the caught exception "the first one the REPL eval" meaning the top form? in this case:
(-> my-obj
-resolve)
?
if that's the case i'd expect that the REPL and the expr:
(try (-> my-obj
-resolve)
(catch js/Object e
e))
will return (or print) the same thing because it sounds that the repl's implicit try/catch of:
(-> my-obj
-resolve)
will do something very similar to this:
(try (-> my-obj
-resolve)
(catch js/Object e
e))
so would you say evaluating this expression:
(try (-> my-obj
-resolve)
(catch :default e (prn e)
:repl/exception!))
should result about the same as just evaluating this expression:
(-> my-obj
-resolve)
?PS
the "full" exception (my exception) indeed appears in *e
after evaluation.
do you know why the repl doesn't print it and instead print only the inner most exception?
sorry but this is absolutely impossible to answer without knowing what your code is actually doing. *e
is bound the the actual (catch :default e)
e exception here. there is no unwrapping or whatever done of any kind, it is also the exact same that is getting printed.
basically in a CLJS REPL there are many involved things happening. there is a lot of async IO and your editor is involved too when using emacs for example
But *e
is not what gets printed.
And I'm asking about the general handling of exceptions in the REPL, how can my code affect it?
If you're asserting that *e
is what should get printed, then I have a curious case here, because it is not.
If e is not what gets printed then my question is what *is get printed (in the general manner).
Sorry your on going answer is great
So your saying that, in my case, calva also has a say
so I'm not entirely sure what you are after. exceptions in JS do not behave like JVM/CLJ exceptions, since there is no inherent "cause" exception. and there is no re-throwing of exceptions.
Maybe some component along the way affects the printing
again ... I cannot give you any more specific answers without knowing the code that is actually throwing the exception
oh and things get even more fun it the exception is part of a react render phase, since you said component I assume that is what you meant
because then likely the whole thing is getting caught by a react error boundary, so your catch
might not actually be the thing catching anything
if you are using the latest shadow-cljs version the exception is also always printed to the browser console, since sometimes that is the best way to see an actual error with proper source mapping and stuff
there was also a change in 2.25.7 affecting REPL errors in general, so maybe if you are not on that version the old behavior was what confuses you? https://github.com/thheller/shadow-cljs/compare/a08f16f8b7b5e929959f797c23384f47fd545a1c...9cc5e7830ceea6adcd814ec551526f13291431a5
generally it should be a bit cleaner now, but *e
was always the caught exception and what got printed, so no change there
I'm not coming with some jvm assumptions because I don't have deep knowledge on how exceptions are handled in the jvm. I meant components in the general sense as a part of the process that prints the exception, no react involved in this phase. My question is quite naive: I construct a detailed error along the execution path but for some reason (that reason is what I'm after) what's printed is corresponding to the error I construct (or what stored in e, which *is the error I constructed). My question is: why I throw one exception and the repl prints another? Is that a normal thing?
> generally it should be a bit cleaner now, but *e was always the caught exception and what got printed, so no change there > This is not what happens in my case e does *not get printed, hence my question...
But if you are certain that *e is what's get printed, then it might be that some component along the tool chain (shadow, calva...) Digs recursively into :cause
because if you'd do that to my error you'd get what is printed in the calva repl.
definitely upgrade shadow-cljs if you are not on 2.25.7+, maybe that solves your question
Thanks, I upgraded to 2.25.8 and that printed the exception to the console. so the situation is this: *e - correct exception console - correct exception output.calva-repl - not full exception (either deepest cause or first exception that been thrown) I'll keep investigating on calva-repl error printing. thanks @U05224H0W for your time and patience