Hi. I've weirdly started getting an error when trying to eval some via C-c C-c, etc: nrepl-dict: An even number of KEY-VALS is needed to build a dict object - details in 🧵
This randomly started happening when I'm connecting to a project that has a lot of deps and uses shadow-cljs to start an nREPL server (with npx shadow-cljs -A:dev:test:tools watch :alias and then I run M-x cider-connect:
;; Connected to nREPL server -
;; CIDER 1.19.0-snapshot (package: 20250619.1159), nREPL 1.1.0
;; Clojure 1.12.1, Java 24.0.1
(I upgraded everything just in case) C-c C-k works to load the main namespace, but when I try and start the server by eval some code, I get what I assue is some basic middleware error. I tried the same thing on a different project (that I start with clj -M,,,) and I don't get the same error. In the project that doesn't work, if I run M-x cider-list-nrepl-middleware I get:
Currently loaded middleware:
But in the project that works I get:
Currently loaded middleware:
* #'nrepl.middleware/wrap-describe
* #'nrepl.middleware.dynamic-loader/wrap-dynamic-loader
* #'nrepl.middleware.completion/wrap-completion
* #'cider.nrepl/wrap-ns
* #'cider.nrepl/wrap-test
* #'cider.nrepl/wrap-log
* #'cider.nrepl/wrap-refresh
* #'nrepl.middleware.interruptible-eval/interruptible-eval
* #'nrepl.middleware.sideloader/wrap-sideloader
* #'nrepl.middleware.load-file/wrap-load-file
* #'nrepl.middleware.session/add-stdin
* #'cider.nrepl/wrap-info
* #'cider.nrepl/wrap-xref
* #'cider.nrepl/wrap-apropos
* #'cider.nrepl/wrap-profile
* #'cider.nrepl/wrap-version
* #'cider.nrepl/wrap-trace
* #'cider.nrepl/wrap-complete
* #'cider.nrepl/wrap-classpath
* #'cider.nrepl/wrap-content-type
* #'cider.nrepl/wrap-clojuredocs
* #'cider.nrepl/wrap-resource
* #'cider.nrepl/wrap-macroexpand
* #'cider.nrepl/wrap-undef
* #'cider.nrepl/wrap-reload
* #'cider.nrepl/wrap-spec
* #'cider.nrepl/wrap-format
* #'cider.nrepl/wrap-stacktrace
* #'cider.nrepl/wrap-slurp
* #'nrepl.middleware.lookup/wrap-lookup
* #'cider.nrepl/wrap-debug
* #'cider.nrepl/wrap-enlighten
* #'cider.piggieback/wrap-cljs-repl
* #'cider.nrepl/wrap-tracker
* #'cider.nrepl/wrap-out
* #'cider.nrepl/wrap-inspect
* #'nrepl.middleware.session/session
* #'nrepl.middleware.caught/wrap-caught
* #'nrepl.middleware.print/wrap-print
I don't see any obvious errors about not being able to load middleware when the shadow-cljs project starts. How do I go about working out whats breaking?there’s something like nrepl-toggle-message or similar. that will show the literal messages going across. hopefully that will let us see which list which represents a map has an uneven number of keys
nrepl-toggle-message-logging?
yes that’s the one
will start logging the messages into a new buffer
I have a buffer called *nrepl-messages trimly/trimly:localhost:8200(clj)* but nothing new get's written into it when I try and eval something
kill the connection and then jack in again?
an error might have already messed everything up
I get some messages during startup (that I can paste here) but again, nothing get's added when I try and eval (+ 1 2 3)
log:
(-->
id "1"
op "clone"
time-stamp "2025-06-20 16:26:41.938886702"
client-name "CIDER"
client-version "1.19.0-snapshot"
)
(<--
id "1"
session "8c452326-5ecf-470e-ae39-70a65623fa78"
time-stamp "2025-06-20 16:26:41.946821806"
new-session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
status ("done")
)
(-->
id "2"
op "clone"
time-stamp "2025-06-20 16:26:41.959667601"
client-name "CIDER"
client-version "1.19.0-snapshot"
)
(<--
id "2"
session "e7377853-c8d2-4969-bc6e-e20c6472bb3c"
time-stamp "2025-06-20 16:26:41.961188008"
new-session "abe3aeb6-fdca-4162-97dc-ecfd39ab432d"
status ("done")
)
(-->
id "3"
op "describe"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:41.980516269"
)
(<--
id "3"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:41.985971291"
aux (dict ...)
ops (dict ...)
status ("done")
versions (dict ...)
)
(-->
id "4"
op "eval"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.003541838"
code "(when-let [requires (resolve 'clojure.main/repl-requires)]
..."
column 1
file "*cider-repl trimly/trimly:localhost:8200(clj)*"
inhibit-cider-middleware "true"
line 10
nrepl.middleware.print/buffer-size 4096
nrepl.middleware.print/options (dict ...)
nrepl.middleware.print/print "cider.nrepl.pprint/pprint"
nrepl.middleware.print/quota 1048576
nrepl.middleware.print/stream? "1"
)
(<--
id "4"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.019270834"
value "nil"
)
(<--
id "4"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.051604582"
ns "shadow.user"
)
(<--
id "4"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.051710937"
status ("done")
)
(-->
id "5"
op "out-subscribe"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.051884279"
)
(-->
id "6"
op "init-debugger"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.052040348"
nrepl.middleware.print/buffer-size 4096
nrepl.middleware.print/options (dict ...)
nrepl.middleware.print/print "cider.nrepl.pprint/pprint"
nrepl.middleware.print/quota 1048576
nrepl.middleware.print/stream? "1"
)
(<--
id "5"
session "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
time-stamp "2025-06-20 16:26:42.066612732"
out-subscribe "cd2c6393-ce8f-46c9-81cb-a82eddf02aa1"
status ("done")
)C-c C-k does however add some stuff to the buffer
which implies to me the error is happening before it even tries to send something to the nrepl connection?
maybe so. there’s an m-x toggle-debug-on-error or similar that could perhaps help out
yes - thanks ... that's useful 😉
still not sure why emacs thinks there's no middleware loaded
it seems like it's this code
(defun cider--nrepl-pr-request-plist ()
"Map to merge into requests that do not require pretty printing."
(let ((print-options (thread-last
cider-print-options
(map-pairs)
(seq-mapcat #'identity)
(apply #'nrepl-dict))))
`("nrepl.middleware.print/print" "cider.nrepl.pprint/pr"
"nrepl.middleware.print/stream?" nil
,@(unless (nrepl-dict-empty-p print-options)
`("nrepl.middleware.print/options" ,print-options))
,@(when cider-print-quota
`("nrepl.middleware.print/quota" ,cider-print-quota)))))
which is triggering the error. I see nrepl-dict(("print-length" nil)) in the stack trace and it turns out i had a (cider-print-options (("print-length" nil))) in the dir-locals for that project. Removed and the eval works again. I'm not sure how this worked last week. I'm not sure when that stopped working but I don't think I updated anything between it working and now.Since :main-opts from multiple aliases don't combine, the approach suggested in the CIDER "https://docs.cider.mx/cider/basics/middleware_setup.html#using-tools-deps" docs of adding an alias in ~/.clojure/deps.edn to load cider-nrepl does not work if you are starting your project using an alias that also has :main-opts used to run the application.
Of course you could combine the :main-opts manually in your alias definition in your project's deps.edn, but that's not optimal: for example, in the fairly common case that a project has some contributors who use CIDER and some who use other tools.
I don't want to use cider-jack-in because I want to start using the project alias and -main to start the application. But then I want to be able to cider-connect with full cider-nrepl functionality once it's running. How are other folks thinking about this?
mains are jealous. I think it’s always worth letting the repl be the main that you use in your editor and then have an easy way to start your application from the repl.
often this is calling the other -main but without any thread-join or system/exits involved