<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent questions tagged stacktrace</title>
<link>https://ask.clojure.org/index.php/tag/stacktrace</link>
<description></description>
<item>
<title>Function to get/set stack-trace of `ex-info`</title>
<link>https://ask.clojure.org/index.php/12227/function-to-get-set-stack-trace-of-ex-info</link>
<description>&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/viesti/timbre-json-appender/pull/29&quot;&gt;Recently&lt;/a&gt;, I fixed a bug in a library that exposed the capability to modify the data within an &lt;code&gt;ex-info&lt;/code&gt; before printing (logging) it, by creating a new &lt;code&gt;ex-info&lt;/code&gt; to store the updated data. This naturally overwrote the existing stack trace on the given &lt;code&gt;ex-info&lt;/code&gt;, so my fix was to use interop to set the stack trace of the new &lt;code&gt;ex-info&lt;/code&gt; to the stack trace of the original &lt;code&gt;ex-info&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(let [cause (process-ex-data-map ex-data-field-fn (ex-cause ex))
      new-ex (ex-info (ex-message ex)
                      (into {} (map (fn [[k v]] {k (ex-data-field-fn v)}) (ex-data ex)))
                      cause)]
  (.setStackTrace ^ExceptionInfo new-ex (.getStackTrace ^ExceptionInfo ex))
  new-ex)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a fine solution, but it feels bad or awkward to be directly modifying the internals of the &lt;code&gt;ex-info&lt;/code&gt;. I understand that &lt;code&gt;ExceptionInfo&lt;/code&gt; probably can't be immutable for interop reasons, but I think it would be helpful if there were functions in &lt;code&gt;clojure.core&lt;/code&gt; that operated on &lt;code&gt;ExceptionInfo&lt;/code&gt;s as if they were immutable.&lt;/p&gt;
&lt;p&gt;Maybe something like this?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(defn ex-stacktrace
  ([ex]
   (when (instance? Throwable ex)
     (.getStackTrace ^Throwable ex)))
  ([ex other]
   (when (and (instance? clojure.lang.ExceptionInfo ex)
              (instance? Throwable other))
     (let [new-ex (ex-info (ex-message ex) (ex-data ex) (ex-cause ex))]
       (.setStackTrace ^clojure.lang.ExceptionInfo new-ex
                       (.getStackTrace ^Throwable other))
       new-ex))))
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Clojure</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/12227/function-to-get-set-stack-trace-of-ex-info</guid>
<pubDate>Tue, 20 Sep 2022 20:08:05 +0000</pubDate>
</item>
<item>
<title>clojure.test deftest exception reporting lists many useless stack frames</title>
<link>https://ask.clojure.org/index.php/10744/clojure-deftest-exception-reporting-lists-useless-frames</link>
<description>&lt;p&gt;If an exception occurs during a clojure.test deftest, the error goes to clojure.test/report with :error key which will (by default) print the entire stack trace. The stack includes the test framework itself and (if invoked via an external test runner like lein test, clojure.main etc), yielding a stack depth of ~60 stack frames which is all incidental noise that is irrelevant.&lt;/p&gt;
&lt;p&gt;There is a dyn var clojure.test/&lt;em&gt;stack-trace-depth&lt;/em&gt; that defaults to nil (all). This dynvar can be bound around calls to the clojure.test runner to see less stack trace when an exception occurs during a test, but this is both difficult to set for external test runners and error prone.&lt;/p&gt;
&lt;p&gt;It would be most useful to filter the framework noise from the bottom of the stack and present only the relevant frames.&lt;/p&gt;
&lt;p&gt;Given a test like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(ns foo.core-test
  (:require [clojure.test :refer :all]))

(deftest a-test
  (testing &quot;FIXME, I fail.&quot;
    (throw (ex-info &quot;I suck&quot; {:a 1}))
    (is (= 0 1))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;the reported error (here from lein test, but any external runner is similar), only the top 2 lines are relevant, the rest is incidental noise:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ERROR in (a-test) (core_test.clj:13)
Uncaught exception, not in assertion.
expected: nil
  actual: clojure.lang.ExceptionInfo: I suck
{:a 1}
 at foo.core_test$fn__364.invokeStatic (core_test.clj:13)
    foo.core_test/fn (core_test.clj:11)
    clojure.test$test_var$fn__9737.invoke (test.clj:717)        ;; noise from here down
    clojure.test$test_var.invokeStatic (test.clj:717)
    clojure.test$test_var.invoke (test.clj:708)
    clojure.test$test_vars$fn__9763$fn__9768.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars$fn__9763.invoke (test.clj:735)
    clojure.test$default_fixture.invokeStatic (test.clj:687)
    clojure.test$default_fixture.invoke (test.clj:683)
    clojure.test$test_vars.invokeStatic (test.clj:731)
    clojure.test$test_all_vars.invokeStatic (test.clj:737)
    clojure.test$test_ns.invokeStatic (test.clj:758)
    clojure.test$test_ns.invoke (test.clj:743)
    user$eval224$fn__287.invoke (form-init4292042596091073068.clj:1)
    clojure.lang.AFn.applyToHelper (AFn.java:156)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.injected$compose_hooks$fn__154.doInvoke (form-init4292042596091073068.clj:1)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.injected$run_hooks.invokeStatic (form-init4292042596091073068.clj:1)
    leiningen.core.injected$run_hooks.invoke (form-init4292042596091073068.clj:1)
    leiningen.core.injected$prepare_for_hooks$fn__159$fn__160.doInvoke (form-init4292042596091073068.clj:1)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$map$fn__5866.invoke (core.clj:2755)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:51)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1792)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.test$run_tests.invokeStatic (test.clj:768)
    clojure.test$run_tests.doInvoke (test.clj:768)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.core$apply.invoke (core.clj:660)
    user$eval224$fn__299$fn__332.invoke (form-init4292042596091073068.clj:1)
    user$eval224$fn__299$fn__300.invoke (form-init4292042596091073068.clj:1)
    user$eval224$fn__299.invoke (form-init4292042596091073068.clj:1)
    user$eval224.invokeStatic (form-init4292042596091073068.clj:1)
    user$eval224.invoke (form-init4292042596091073068.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:7177)
    clojure.lang.Compiler.eval (Compiler.java:7167)
    clojure.lang.Compiler.load (Compiler.java:7636)
    clojure.lang.Compiler.loadFile (Compiler.java:7574)
    clojure.main$load_script.invokeStatic (main.clj:475)
    clojure.main$init_opt.invokeStatic (main.clj:477)
    clojure.main$init_opt.invoke (main.clj:477)
    clojure.main$initialize.invokeStatic (main.clj:508)
    clojure.main$null_opt.invokeStatic (main.clj:542)
    clojure.main$null_opt.invoke (main.clj:539)
    clojure.main$main.invokeStatic (main.clj:664)
    clojure.main$main.doInvoke (main.clj:616)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:40)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We are doing things elsewhere to filter frames and I don't think it would be that hard to filter this to improve the default experience (could still be a dyn var to not filter if needed).&lt;/p&gt;
</description>
<category>Test</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10744/clojure-deftest-exception-reporting-lists-useless-frames</guid>
<pubDate>Wed, 30 Jun 2021 07:10:59 +0000</pubDate>
</item>
<item>
<title>Better stacktraces for protocol methods</title>
<link>https://ask.clojure.org/index.php/9775/better-stacktraces-for-protocol-methods</link>
<description>&lt;p&gt;Currently extend-protocol-defined functions look like this in the stacktrace:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;at app.core$eval3547$fn__3548.invoke(core.clj:23)
at app.core$eval3522$fn__3523$G__3513__3532.invoke(core.clj:14)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Needless to say these aren't exactly descriptive. Not to mention the lines it refers to are where extend-protocol and defprotocol were called, not where the function definition is.&lt;/p&gt;
&lt;p&gt;I'd hope for something like &lt;code&gt;app.core/MyProtocol/IfaceImplemented/function_name_1234&lt;/code&gt; with the line number where the &quot;offending&quot; piece of code is, not the definition.&lt;/p&gt;
&lt;p&gt;I hacked at it a little locally and found that changing emit-method-builder, emit-impl and emit-hinted-impl a little made the stacktraces much more readable.&lt;/p&gt;
&lt;p&gt;Hack diff:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index 786f0d4b..73570dbf 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -586,9 +586,10 @@
 
 (defn- emit-method-builder [on-interface method on-method arglists extend-via-meta]
   (let [methodk (keyword method)
-        gthis (with-meta (gensym) {:tag 'clojure.lang.AFunction})
-        ginterf (gensym)]
-    `(fn [cache#]
+        gthis (with-meta (gensym (str method)) {:tag 'clojure.lang.AFunction})
+        ginterf (gensym)
+        giface-name (gensym (last (.split (name on-interface) &quot;\\.&quot;)))]
+    `(fn ~giface-name [cache#]
        (let [~ginterf
              (fn
                ~@(map 
@@ -812,9 +813,21 @@
                    (:var proto)))))
     (-reset-methods (alter-var-root (:var proto) assoc-in [:impls atype] mmap))))
 
+(defn- iface-fn-name
+  ([p f]
+   (iface-fn-name &quot;&quot; p f))
+  ([c p f]
+   (let [c-name (cond
+                  (symbol? c)
+                    (last (.split (name c) &quot;\\.&quot;))
+                  (nil? c)
+                    &quot;nil&quot;
+                  :else nil)]
+     (symbol (str p (when c-name (str &quot;__&quot; c-name)) (first f))))))
+
 (defn- emit-impl [[p fs]]
   [p (zipmap (map #(-&amp;gt; % first keyword) fs)
-             (map #(cons `fn (drop 1 %)) fs))])
+             (map #(cons `fn (cons (iface-fn-name p %) (drop 1 %))) fs))])
 
 (defn- emit-hinted-impl [c [p fs]]
   (let [hint (fn [specs]
@@ -826,7 +839,7 @@
                               body))
                       specs)))]
     [p (zipmap (map #(-&amp;gt; % first name keyword) fs)
-               (map #(cons `fn (hint (drop 1 %))) fs))]))
+               (map #(cons `fn (cons (iface-fn-name c p %) (hint (drop 1 %)))) fs))]))
 
 (defn- emit-extend-type [c specs]
   (let [impls (parse-impls specs)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Logs after:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;at app.core$eval3965$ProtocolName__ClassName__FnName__3966.invoke(core.clj:23)
at app.core$eval3940$ProtocolName3932__3941$__FnName3930__3950.invoke(core.clj:14)
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Protocols</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/9775/better-stacktraces-for-protocol-methods</guid>
<pubDate>Tue, 10 Nov 2020 05:30:20 +0000</pubDate>
</item>
<item>
<title>How to display better errors in clojure stacktraces? is this planned to be attacked on a new clojure version?</title>
<link>https://ask.clojure.org/index.php/8343/display-clojure-stacktraces-planned-attacked-clojure-version</link>
<description>&lt;p&gt;Clojure stacktraces are pretty cryptic and hard to follow, is there a library to display better errors or format the stacktraces?&lt;/p&gt;
</description>
<category>Errors</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8343/display-clojure-stacktraces-planned-attacked-clojure-version</guid>
<pubDate>Tue, 06 Aug 2019 14:09:25 +0000</pubDate>
</item>
<item>
<title>How do I get a full stack trace instead of &quot;... 12 more&quot;?</title>
<link>https://ask.clojure.org/index.php/8207/how-do-i-get-a-full-stack-trace-instead-of-12-more</link>
<description>&lt;p&gt;Using &lt;code&gt;lein run&lt;/code&gt;. There are no references to my *.clj file anywhere, so I don't know where this &lt;code&gt;java.lang.NullPointerException&lt;/code&gt; is coming from??&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Exception in thread &quot;main&quot; Syntax error compiling at (/tmp/form-init542794133375754487.clj:1:72).
    at clojure.lang.Compiler.load(Compiler.java:7647)
    at clojure.lang.Compiler.loadFile(Compiler.java:7573)
    at clojure.main$load_script.invokeStatic(main.clj:452)
    at clojure.main$init_opt.invokeStatic(main.clj:454)
    at clojure.main$init_opt.invoke(main.clj:454)
    at clojure.main$initialize.invokeStatic(main.clj:485)
    at clojure.main$null_opt.invokeStatic(main.clj:519)
    at clojure.main$null_opt.invoke(main.clj:516)
    at clojure.main$main.invokeStatic(main.clj:598)
    at clojure.main$main.doInvoke(main.clj:561)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.lang.Var.applyTo(Var.java:705)
    at clojure.main.main(main.java:37)
Caused by: java.lang.NullPointerException
    at xinova.model$reload_dbs.invokeStatic(model.clj:78)
    at xinova.model$reload_dbs.invoke(model.clj:78)
    at xinova.core$_main.invokeStatic(core.clj:18)
    at xinova.core$_main.doInvoke(core.clj:14)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.lang.Var.invoke(Var.java:384)
    at user$eval140.invokeStatic(form-init542794133375754487.clj:1)
    at user$eval140.invoke(form-init542794133375754487.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:7176)
    at clojure.lang.Compiler.eval(Compiler.java:7166)
    at clojure.lang.Compiler.load(Compiler.java:7635)
    ... 12 more
&lt;/code&gt;&lt;/pre&gt;
</description>
<category>Errors</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8207/how-do-i-get-a-full-stack-trace-instead-of-12-more</guid>
<pubDate>Fri, 26 Jul 2019 19:10:03 +0000</pubDate>
</item>
</channel>
</rss>