cider icon indicating copy to clipboard operation
cider copied to clipboard

`cider-stacktrace-render` works incorrectly for ClojureScript

Open rrudakov opened this issue 5 months ago • 1 comments

Expected behavior

When I eval a ClojureScript expression that causes an exception, *cider-error* buffer is displayed with the exception data.

Actual behavior

The *cider-error* buffer contains only the following text:


  Show: Project-Only All 
  Hide: Clojure Java REPL Tooling Duplicates  (0 frames hidden)

and the following error is signaled:

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  propertize(nil font-lock-face cider-stacktrace-error-class-face mouse-face highlight)
  (insert (format "%d. " num) (propertize note 'font-lock-face 'font-lock-comment-face) " " (propertize class 'font-lock-face class-face 'mouse-face 'highlight) "\n")
  (progn (insert (format "%d. " num) (propertize note 'font-lock-face 'font-lock-comment-face) " " (propertize class 'font-lock-face class-face 'mouse-face 'highlight) "\n"))
  (prog1 (progn (insert (format "%d. " num) (propertize note 'font-lock-face 'font-lock-comment-face) " " (propertize class 'font-lock-face class-face 'mouse-face 'highlight) "\n")) (add-text-properties start (point) (list 'detail 0 'inspect-index inspect-index 'keymap cider-stacktrace-exception-map)))
  (let ((start (point))) (prog1 (progn (insert (format "%d. " num) (propertize note 'font-lock-face 'font-lock-comment-face) " " (propertize class 'font-lock-face class-face 'mouse-face 'highlight) "\n")) (add-text-properties start (point) (list 'detail 0 'inspect-index inspect-index 'keymap cider-stacktrace-exception-map))))
  (progn (let ((start (point))) (prog1 (progn (insert (format "%d. " num) (propertize note 'font-lock-face 'font-lock-comment-face) " " (propertize class 'font-lock-face class-face 'mouse-face 'highlight) "\n")) (add-text-properties start (point) (list 'detail 0 'inspect-index inspect-index 'keymap cider-stacktrace-exception-map)))) (let ((start (point))) (prog1 (progn (if (equal class "clojure.lang.Compiler$CompilerException") (cider-stacktrace-render-compile-error buffer cause) (cider-stacktrace-emit-indented (propertize (or message "(No message)") 'font-lock-face message-face) indent t)) (if triage (progn (insert "\n") (cider-stacktrace-emit-indented (propertize ... ... message-face) indent nil))) (if spec (progn (insert "\n") (cider-stacktrace--emit-spec-problems spec (concat indent "  ")))) (if data (progn (insert "\n") (let (...) (prog1 ... ...)))) (insert "\n")) (add-text-properties start (point) '(detail 1)))) (let ((start (point))) (prog1 (progn (let ((beg (point)) (bg (cons ... ...))) (let ((tail stacktrace)) (while tail (let ... ... ... ...))) (overlay-put (make-overlay beg (point)) 'font-lock-face bg))) (add-text-properties start (point) '(detail 2)))) (let ((start (point))) (prog1 (progn (insert "\n")) (add-text-properties start (point) '(detail 0)))))
  (prog1 (progn (let ((start (point))) (prog1 (progn (insert (format "%d. " num) (propertize note 'font-lock-face 'font-lock-comment-face) " " (propertize class 'font-lock-face class-face 'mouse-face 'highlight) "\n")) (add-text-properties start (point) (list 'detail 0 'inspect-index inspect-index 'keymap cider-stacktrace-exception-map)))) (let ((start (point))) (prog1 (progn (if (equal class "clojure.lang.Compiler$CompilerException") (cider-stacktrace-render-compile-error buffer cause) (cider-stacktrace-emit-indented (propertize ... ... message-face) indent t)) (if triage (progn (insert "\n") (cider-stacktrace-emit-indented ... indent nil))) (if spec (progn (insert "\n") (cider-stacktrace--emit-spec-problems spec ...))) (if data (progn (insert "\n") (let ... ...))) (insert "\n")) (add-text-properties start (point) '(detail 1)))) (let ((start (point))) (prog1 (progn (let ((beg ...) (bg ...)) (let (...) (while tail ...)) (overlay-put (make-overlay beg ...) 'font-lock-face bg))) (add-text-properties start (point) '(detail 2)))) (let ((start (point))) (prog1 (progn (insert "\n")) (add-text-properties start (point) '(detail 0))))) (add-text-properties start (point) (list 'cause num)))
  (let ((start (point))) (prog1 (progn (let ((start (point))) (prog1 (progn (insert (format "%d. " num) (propertize note ... ...) " " (propertize class ... class-face ... ...) "\n")) (add-text-properties start (point) (list 'detail 0 'inspect-index inspect-index 'keymap cider-stacktrace-exception-map)))) (let ((start (point))) (prog1 (progn (if (equal class "clojure.lang.Compiler$CompilerException") (cider-stacktrace-render-compile-error buffer cause) (cider-stacktrace-emit-indented ... indent t)) (if triage (progn ... ...)) (if spec (progn ... ...)) (if data (progn ... ...)) (insert "\n")) (add-text-properties start (point) '(detail 1)))) (let ((start (point))) (prog1 (progn (let (... ...) (let ... ...) (overlay-put ... ... bg))) (add-text-properties start (point) '(detail 2)))) (let ((start (point))) (prog1 (progn (insert "\n")) (add-text-properties start (point) '(detail 0))))) (add-text-properties start (point) (list 'cause num))))
  (let ((indent "   ") (class-face 'cider-stacktrace-error-class-face) (message-face 'cider-stacktrace-error-message-face)) (let ((start (point))) (prog1 (progn (let ((start (point))) (prog1 (progn (insert ... ... " " ... "\n")) (add-text-properties start (point) (list ... 0 ... inspect-index ... cider-stacktrace-exception-map)))) (let ((start (point))) (prog1 (progn (if ... ... ...) (if triage ...) (if spec ...) (if data ...) (insert "\n")) (add-text-properties start (point) '...))) (let ((start (point))) (prog1 (progn (let ... ... ...)) (add-text-properties start (point) '...))) (let ((start (point))) (prog1 (progn (insert "\n")) (add-text-properties start (point) '...)))) (add-text-properties start (point) (list 'cause num)))))
  (let ((class (nrepl-dict-get cause "class")) (message (nrepl-dict-get cause "message")) (data (nrepl-dict-get cause "data")) (spec (nrepl-dict-get cause "spec")) (triage (nrepl-dict-get cause "triage")) (stacktrace (nrepl-dict-get cause "stacktrace"))) (let ((indent "   ") (class-face 'cider-stacktrace-error-class-face) (message-face 'cider-stacktrace-error-message-face)) (let ((start (point))) (prog1 (progn (let ((start ...)) (prog1 (progn ...) (add-text-properties start ... ...))) (let ((start ...)) (prog1 (progn ... ... ... ... ...) (add-text-properties start ... ...))) (let ((start ...)) (prog1 (progn ...) (add-text-properties start ... ...))) (let ((start ...)) (prog1 (progn ...) (add-text-properties start ... ...)))) (add-text-properties start (point) (list 'cause num))))))
  (save-current-buffer (set-buffer buffer) (let ((class (nrepl-dict-get cause "class")) (message (nrepl-dict-get cause "message")) (data (nrepl-dict-get cause "data")) (spec (nrepl-dict-get cause "spec")) (triage (nrepl-dict-get cause "triage")) (stacktrace (nrepl-dict-get cause "stacktrace"))) (let ((indent "   ") (class-face 'cider-stacktrace-error-class-face) (message-face 'cider-stacktrace-error-message-face)) (let ((start (point))) (prog1 (progn (let (...) (prog1 ... ...)) (let (...) (prog1 ... ...)) (let (...) (prog1 ... ...)) (let (...) (prog1 ... ...))) (add-text-properties start (point) (list 'cause num)))))))
  cider-stacktrace-render-cause(#<buffer *cider-error*> (dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error")) 1 "Unhandled" 0)
  (let ((note (if (= num causes-length) "Unhandled" "Caused by"))) (cider-stacktrace-render-cause buffer cause num note (- causes-length num)) (setq num (1- num)))
  (let ((cause (car tail))) (let ((note (if (= num causes-length) "Unhandled" "Caused by"))) (cider-stacktrace-render-cause buffer cause num note (- causes-length num)) (setq num (1- num))) (setq tail (cdr tail)))
  (while tail (let ((cause (car tail))) (let ((note (if (= num causes-length) "Unhandled" "Caused by"))) (cider-stacktrace-render-cause buffer cause num note (- causes-length num)) (setq num (1- num))) (setq tail (cdr tail))))
  (let ((tail causes)) (while tail (let ((cause (car tail))) (let ((note (if (= num causes-length) "Unhandled" "Caused by"))) (cider-stacktrace-render-cause buffer cause num note (- causes-length num)) (setq num (1- num))) (setq tail (cdr tail)))))
  (let* ((causes-length (length causes)) (num causes-length)) (let ((tail causes)) (while tail (let ((cause (car tail))) (let ((note (if ... "Unhandled" "Caused by"))) (cider-stacktrace-render-cause buffer cause num note (- causes-length num)) (setq num (1- num))) (setq tail (cdr tail))))))
  (let ((inhibit-read-only t)) (erase-buffer) (insert "\n") (cider-stacktrace-render-filters buffer '(("Project-Only" project) ("All" all)) '(("Clojure" clj) ("Java" java) ("REPL" repl) ("Tooling" tooling) ("Duplicates" dup))) (insert "\n") (if error-types (progn (cider-stacktrace-render-suppression-toggle buffer error-types) (insert "\n\n"))) (let* ((causes-length (length causes)) (num causes-length)) (let ((tail causes)) (while tail (let ((cause (car tail))) (let ((note ...)) (cider-stacktrace-render-cause buffer cause num note (- causes-length num)) (setq num (1- num))) (setq tail (cdr tail)))))))
  (save-current-buffer (set-buffer buffer) (let ((inhibit-read-only t)) (erase-buffer) (insert "\n") (cider-stacktrace-render-filters buffer '(("Project-Only" project) ("All" all)) '(("Clojure" clj) ("Java" java) ("REPL" repl) ("Tooling" tooling) ("Duplicates" dup))) (insert "\n") (if error-types (progn (cider-stacktrace-render-suppression-toggle buffer error-types) (insert "\n\n"))) (let* ((causes-length (length causes)) (num causes-length)) (let ((tail causes)) (while tail (let ((cause ...)) (let (...) (cider-stacktrace-render-cause buffer cause num note ...) (setq num ...)) (setq tail (cdr tail))))))) (cider-stacktrace-initialize causes) (font-lock-refresh-defaults))
  cider-stacktrace-render(#<buffer *cider-error*> ((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error"))) nil)
  (let* ((repl (or repl (cider-current-repl))) (error-buffer (cider-new-error-buffer #'cider-stacktrace-mode error-types is-compilation))) (save-current-buffer (set-buffer error-buffer) (setq cider--ancillary-buffer-repl repl)) (cider-stacktrace-render error-buffer causes error-types))
  (progn (let* ((repl (or repl (cider-current-repl))) (error-buffer (cider-new-error-buffer #'cider-stacktrace-mode error-types is-compilation))) (save-current-buffer (set-buffer error-buffer) (setq cider--ancillary-buffer-repl repl)) (cider-stacktrace-render error-buffer causes error-types)))
  (if causes (progn (let* ((repl (or repl (cider-current-repl))) (error-buffer (cider-new-error-buffer #'cider-stacktrace-mode error-types is-compilation))) (save-current-buffer (set-buffer error-buffer) (setq cider--ancillary-buffer-repl repl)) (cider-stacktrace-render error-buffer causes error-types))))
  cider--render-stacktrace-causes(((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error"))) nil nil #<buffer *cider-repl Projects/cljs-tutorial:localhost:61718(cljs:browser)*>)
  cider--handle-stacktrace-response(((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error"))) nil #<buffer *cider-repl Projects/cljs-tutorial:localhost:61718(cljs:browser)*>)
  #f(lambda (causes phase) [(buffer #<buffer *cider-repl Projects/cljs-tutorial:localhost:61718(cljs:browser)*>)] (cider--handle-stacktrace-response causes phase buffer))(((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error"))) nil)
  funcall(#f(lambda (causes phase) [(buffer #<buffer *cider-repl Projects/cljs-tutorial:localhost:61718(cljs:browser)*>)] (cider--handle-stacktrace-response causes phase buffer)) ((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error"))) nil)
  (if (member "done" status) (funcall callback causes ex-phase) (if phase (progn (setq ex-phase phase))) (setq causes (append causes (list response))))
  (let ((status (nrepl-dict-get response "status")) (phase (nrepl-dict-get response "phase"))) (if (member "done" status) (funcall callback causes ex-phase) (if phase (progn (setq ex-phase phase))) (setq causes (append causes (list response)))))
  #f(lambda (response) [(ex-phase nil) (causes ((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("no-error")))) (callback #f(lambda (causes phase) [(buffer #<buffer *cider-repl Projects/cljs-tutorial:localhost:61718(cljs:browser)*>)] (cider--handle-stacktrace-response causes phase buffer)))] (let ((status (nrepl-dict-get response "status")) (phase (nrepl-dict-get response "phase"))) (if (member "done" status) (funcall callback causes ex-phase) (if phase (progn (setq ex-phase phase))) (setq causes (append causes (list response))))))((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("done")))
  nrepl--dispatch-response((dict "id" "134" "session" "4a471f61-529b-4398-aa85-59891c1c8fde" "status" ("done")))
  nrepl-client-filter(#<process nrepl-connection> "d2:id3:1347:session36:4a471f61-529b-4398-aa85-59891c1c8fde6:statusl8:no-erroreed2:id3:1347:session36:4a471f61-529b-4398-aa85-59891c1c8fde6:statusl4:doneee")

Steps to reproduce the problem

  1. Create a simple hello world ClojureScript project from the quick start tutorial.
  2. Evaluate any form that throws an exception either in the REPL buffer or in the source buffer. For example:
(throw (ex-info "Error" {:some "Data"}))

;; or

(ffirst [1])

Notes after some debugging

  1. The error is signaled from the cider-stacktrace-render-cause function, because class is nil in the expression (propertize class 'font-lock-face class-face 'mouse-face 'highlight).
  2. I tried to comment the problematic expression, the error is gone but the *cider-error* buffer shows not very useful information:
Image

Environment & Version information

CIDER version information

;; CIDER 1.18.0 (Athens), nREPL 1.3.1
;; Clojure 1.12.0, Java 23.0.2

Lein / Clojure CLI version

Clojure CLI 1.12

Emacs version

GNU Emacs 31.0.50 (build 1, aarch64-apple-darwin24.4.0, NS appkit-2575.50 Version 15.4.1 (Build 24E263)) of 2025-04-29

Operating system

MacOS

JDK distribution

openjdk version "23.0.2" 2025-01-21 OpenJDK Runtime Environment Homebrew (build 23.0.2) OpenJDK 64-Bit Server VM Homebrew (build 23.0.2, mixed mode, sharing)

rrudakov avatar May 17 '25 07:05 rrudakov