At work we just ran into a situation where Clojure was trying to report-error
, which calls pprint
on the exception, and the ex-data
in the exception is not printable so printing code blew up so you lose the exception information completely. Would there be interest in making report-error
more robust so you still get useful output from it, or would this be considered too much of an edge case?
non printable ex-data is weird to me, as I rarely use ex-data for anything other than printing (so I know more about the exception context in the printed output)
Specifically, this is a case where ex-data
is essentially a lazy sequence and realizing it throws an exception (it’s a bit more complex than that but…).
Hmm, in trying to boil this down to a simpler repro case, I can’t actually get a version that loses exception data like we’re seeing at work.
Example of what I’m talking about:
(! 536)-> cat blowup.clj
(def bad (delay (/ 1 0)))
(def wrap (lazy-seq (cons @bad [])))
(throw (ex-info "boom" {:explode wrap}))
(! 537)-> clojure -M blowup.clj
Exception in thread "main" java.lang.ArithmeticException: Divide by zero
at clojure.lang.Numbers.divide(Numbers.java:188)
at clojure.lang.Numbers.divide(Numbers.java:3901)
at user$fn__136.invokeStatic(blowup.clj:1)
at user$fn__136.invoke(blowup.clj:1)
at clojure.lang.Delay.deref(Delay.java:42)
at clojure.core$deref.invokeStatic(core.clj:2324)
at clojure.core$deref.invoke(core.clj:2310)
at user$fn__138.invokeStatic(blowup.clj:3)
at user$fn__138.invoke(blowup.clj:3)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
...
at clojure.pprint$pprint.invoke(pprint_base.clj:241)
at clojure.lang.Var.invoke(Var.java:384)
at clojure.main$report_error$fn__9184$fn__9185.invoke(main.clj:603)
at clojure.main$report_error$fn__9184.invoke(main.clj:602)
at clojure.main$report_error.invokeStatic(main.clj:601)
at clojure.main$main.invokeStatic(main.clj:666)
at clojure.main$main.doInvoke(main.clj:616)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at clojure.lang.Var.applyTo(Var.java:705)
at clojure.main.main(main.java:40)
Instead of getting a single line error and an EDN file. You get the underlying exception but you don’t get any info about the ex-info
that was actually thrown.