clojure-emacs / cider-nrepl

A collection of nREPL middleware to enhance Clojure editors with common functionality like definition lookup, code completion, etc.
https://docs.cider.mx/cider-nrepl
684 stars 176 forks source link

ClassCastException in cider middleware, when evaluating forms through an unix domain socket connection #727

Closed bendlas closed 2 years ago

bendlas commented 3 years ago

Expected behavior

Connecting to nrepl and evaluating forms via unix domain socket connection works on latest JDK

Actual behavior

After connecting successfully, evaluating forms throws java.nio.HeapByteBuffer cannot be cast to class [Ljava.nio.ByteBuffer;

Exception updating the ns-cache #error {
 :cause class java.nio.HeapByteBuffer cannot be cast to class [Ljava.nio.ByteBuffer; (java.nio.HeapByteBuffer and [Ljava.nio.ByteBuffer; are in module java.base of loader 'bootstrap')
 :via
 [{:type java.lang.ClassCastException
   :message class java.nio.HeapByteBuffer cannot be cast to class [Ljava.nio.ByteBuffer; (java.nio.HeapByteBuffer and [Ljava.nio.ByteBuffer; are in module java.base of loader 'bootstrap')
   :at [nrepl.socket.BufferedOutputChannel write socket.clj 207]}]
 :trace
 [[nrepl.socket.BufferedOutputChannel write socket.clj 207]
  [nrepl.socket.BufferedOutputChannel write socket.clj 202]
  [nrepl.transport$safe_write_bencode invokeStatic transport.clj 112]
  [nrepl.transport$safe_write_bencode invoke transport.clj 103]
  [nrepl.transport$bencode$fn__731 invoke transport.clj 130]
  [nrepl.transport.FnTransport send transport.clj 34]
  [nrepl.transport$eval637$fn__638$G__629__641 invoke transport.clj 23]
  [nrepl.transport$eval637$fn__638$G__628__645 invoke transport.clj 23]
  [clojure.lang.Var invoke Var.java 388]
  [cider.nrepl.middleware.track_state$update_and_send_cache$fn__7173 invoke track_state.clj 213]
  [cider.nrepl.middleware.track_state$update_and_send_cache invokeStatic track_state.clj 209]
  [cider.nrepl.middleware.track_state$update_and_send_cache invoke track_state.clj 159]
  [cider.nrepl.middleware.track_state$update_and_send_cache invokeStatic track_state.clj 181]
  [cider.nrepl.middleware.track_state$update_and_send_cache invoke track_state.clj 159]
  [clojure.lang.AFn applyToHelper AFn.java 156]
  [clojure.lang.AFn applyTo AFn.java 144]
  [clojure.core$apply invokeStatic core.clj 667]
  [clojure.core$update_in$up__6853 invoke core.clj 6185]
  [clojure.core$update_in invokeStatic core.clj 6186]
  [clojure.core$update_in doInvoke core.clj 6172]
  [clojure.lang.RestFn applyTo RestFn.java 146]
  [clojure.core$apply invokeStatic core.clj 671]
  [clojure.core$binding_conveyor_fn$fn__5754 doInvoke core.clj 2041]
  [clojure.lang.RestFn applyTo RestFn.java 146]
  [clojure.lang.Agent$Action doRun Agent.java 114]
  [clojure.lang.Agent$Action run Agent.java 163]
  [java.util.concurrent.ThreadPoolExecutor runWorker ThreadPoolExecutor.java 1136]
  [java.util.concurrent.ThreadPoolExecutor$Worker run ThreadPoolExecutor.java 635]
  [java.lang.Thread run Thread.java 833]]}

Steps to reproduce the problem

I used the following method:

lein with-profile +nrepl run -m clojure.main -e "(do (require 'nrepl.server) (require 'cider.nrepl.middleware) (require 'refactor-nrepl.middleware) (nrepl.server/start-server :socket \"nrepl.sock\" :handler (apply nrepl.server/default-handler (conj cider.nrepl.middleware/cider-middleware #'refactor-nrepl.middleware/wrap-refactor))))"

Connect from emacs cider.el with https://github.com/clojure-emacs/cider/pull/3088

I couldn't figure out how to connect from nrepl.cmdline (sorry), but I'm reasonably confident that the problem is in the cider middlware, because when starting the server without middleware, the connection works.

Environment & Version information

cider-nrepl version

0.27.2

Java version

17.0.1

Operating system

NixOS Linux

bendlas commented 3 years ago

Note: on JDK11 with com.kohlschutter.junixsocket/junixsocket-core, this works as well.

bbatsov commented 3 years ago

Probably another wrong type annotation? @rlbdv can you look into this?

rlbdv commented 2 years ago

Yep.

rlbdv commented 2 years ago

I'll see if I can set things up to reproduce the problem, but also wondered if we already knew what class was being passed as the channel in that socket.clj (.write ...)?

rlbdv commented 2 years ago

@bendlas I was trying to follow your instructions, and the lein run command fails because refactor-nrepl.middleware is mssing. I'm guessing either I don't have something set up right, or that's a local file?

vemv commented 2 years ago

I reckon you can change the command to

lein with-profile +nrepl run -m clojure.main -e "(do (require 'nrepl.server) (require 'cider.nrepl.middleware) (nrepl.server/start-server :socket \"nrepl.sock\" :handler (apply nrepl.server/default-handler cider.nrepl.middleware/cider-middleware)))"

i.e. with the refactor-nrepl middleware removed. refactor-nrepl almost certainly has nothing to do with the issue so it's safe to remove it.

rlbdv commented 2 years ago

Great - I can at least reproduce it.

rlbdv commented 2 years ago

Got it - should be able to post a fix tomorrow.

bbatsov commented 2 years ago

Great, thanks for the update!

bbatsov commented 2 years ago

This should be fixed in nREPL 0.9.0-beta5.