Occasionally you’ll hit an exception when calling into Java code and the REPL will tell you the message but not the stack trace:
user=> (java.util.Date. "foo") java.lang.IllegalArgumentException (NO_SOURCE_FILE:0)
The last exception is stored in *e by the REPL and you can use the Clojure stacktrace API to examine it more closely:
user=> (use 'clojure.stacktrace)
nil
user=> (print-stack-trace *e 5)
clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval (Compiler.java:4658)
clojure.core/eval (core.clj:2035)
clojure.main$repl__7403$read_eval_print__7415.invoke (main.clj:183)
clojure.main$repl__7403.doInvoke (main.clj:200)
clojure.lang.RestFn.invoke (RestFn.java:426)
Here I dumped just the top 5 frames of the top-level exception. But I really want the cause of the exception not the wrapper exception created in the compiler. You can dump all the traces in the chain like this:
user=> (print-cause-trace *e 3)
clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval (Compiler.java:4658)
clojure.core/eval (core.clj:2035)
clojure.main$repl__7403$read_eval_print__7415.invoke (main.clj:183)
Caused by: java.lang.IllegalArgumentException: null
at java.util.Date.parse (Date.java:598)
java.util.Date.<init> (Date.java:255)
user/eval (NO_SOURCE_FILE:225)
Or print only the root cause like this:
user=> (print-stack-trace (root-cause *e) 3)
java.lang.IllegalArgumentException: null
at java.util.Date.parse (Date.java:598)
java.util.Date.<init> (Date.java:255)
user/eval (NO_SOURCE_FILE:225)
Of course you can always just treat the *e as a Throwable and call normal Java methods on it too:
user=> (.printStackTrace *e)
java.lang.IllegalArgumentException (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:4658)
at clojure.core$eval__5254.invoke(core.clj:2035)
at clojure.main$repl__7403$read_eval_print__7415.invoke(main.clj:183)
at clojure.main$repl__7403.doInvoke(main.clj:200)
at clojure.lang.RestFn.invoke(RestFn.java:426)
at clojure.main$repl_opt__7449.invoke(main.clj:254)
at clojure.main$main__7484.doInvoke(main.clj:341)
at clojure.lang.RestFn.invoke(RestFn.java:402)
at clojure.lang.Var.invoke(Var.java:355)
at clojure.lang.AFn.applyToHelper(AFn.java:171)
at clojure.lang.Var.applyTo(Var.java:476)
at clojure.main.main(main.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at jline.ConsoleRunner.main(ConsoleRunner.java:69)
Caused by: java.lang.IllegalArgumentException
at java.util.Date.parse(Date.java:598)
at java.util.Date.<init>(Date.java:255)
at user$eval__362.invoke(NO_SOURCE_FILE:249)
at clojure.lang.Compiler.eval(Compiler.java:4642)
... 16 more
Happy hunting!
