clojure-emacs/cider

Couldn't create directories error with cider.enrich-classpath/middleware

Closed this issue ยท 17 comments

Expected behavior

Cider jack-in works.

Actual behavior

Cider jack-in fails as from very recently. It has a stack-trace in the Messages buffer. When I copy the lein startup command to bash, the same command fails in the same way.

Commands that correctly starts the repl on the command-line:

  • lein repl :headless
  • /usr/local/bin/lein update-in :dependencies conj \[nrepl/nrepl\ \"0.9.0\"\] -- update-in :plugins conj \[refactor-nrepl/refactor-nrepl\ \"3.1.0\"\] -- update-in :plugins conj \[cider/cider-nrepl\ \"0.27.4\"\] -- repl :headless :host localhost

Steps to reproduce the problem

On the command line, run this command which is what cider uses to jack in to the repl:

/usr/local/bin/lein update-in :dependencies conj \[nrepl/nrepl\ \"0.9.0\"\] -- update-in :plugins conj \[refactor-nrepl/refactor-nrepl\ \"3.1.0\"\] -- update-in :plugins conj \[cider/cider-nrepl\ \"0.27.4\"\] -- update-in :plugins conj \[mx.cider/enrich-classpath\ \"1.5.1\"\] -- update-in :middleware conj cider.enrich-classpath/middleware -- repl :headless :host localhost

If you look closely, you'll see this section triggers the error: -- update-in :middleware conj cider.enrich-classpath/middleware

Stack trace

java.lang.Exception: Couldn't create directories: 
 at leiningen.core.utils$mkdirs.invokeStatic (utils.clj:72)
    leiningen.core.utils$mkdirs.invoke (utils.clj:67)
    leiningen.core.eval$prep.invokeStatic (eval.clj:83)
    leiningen.core.eval$prep.invoke (eval.clj:73)
    leiningen.core.eval$eval_in_project.invokeStatic (eval.clj:364)
    leiningen.core.eval$eval_in_project.invoke (eval.clj:358)
    clojure.lang.AFn.applyToHelper (AFn.java:160)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.repl$repl.invokeStatic (repl.clj:393)
    leiningen.repl$repl.doInvoke (repl.clj:319)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$partial_task$fn__7356.doInvoke (main.clj:284)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:343)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.update_in$update_in.invokeStatic (update_in.clj:37)
    leiningen.update_in$update_in.doInvoke (update_in.clj:24)
    clojure.lang.RestFn.applyTo (RestFn.java:146)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$partial_task$fn__7356.doInvoke (main.clj:284)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:343)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.update_in$update_in.invokeStatic (update_in.clj:37)
    leiningen.update_in$update_in.doInvoke (update_in.clj:24)
    clojure.lang.RestFn.applyTo (RestFn.java:146)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$partial_task$fn__7356.doInvoke (main.clj:284)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:343)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.update_in$update_in.invokeStatic (update_in.clj:37)
    leiningen.update_in$update_in.doInvoke (update_in.clj:24)
    clojure.lang.RestFn.applyTo (RestFn.java:146)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$partial_task$fn__7356.doInvoke (main.clj:284)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:343)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.update_in$update_in.invokeStatic (update_in.clj:37)
    leiningen.update_in$update_in.doInvoke (update_in.clj:24)
    clojure.lang.RestFn.applyTo (RestFn.java:146)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$partial_task$fn__7356.doInvoke (main.clj:284)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:343)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.update_in$update_in.invokeStatic (update_in.clj:37)
    leiningen.update_in$update_in.doInvoke (update_in.clj:24)
    clojure.lang.RestFn.applyTo (RestFn.java:146)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$partial_task$fn__7356.doInvoke (main.clj:284)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.lang.AFunction$1.doInvoke (AFunction.java:31)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invokeStatic (core.clj:667)
    clojure.core$apply.invoke (core.clj:660)
    leiningen.core.main$apply_task.invokeStatic (main.clj:334)
    leiningen.core.main$apply_task.invoke (main.clj:320)
    leiningen.core.main$resolve_and_apply.invokeStatic (main.clj:343)
    leiningen.core.main$resolve_and_apply.invoke (main.clj:336)
    leiningen.core.main$_main$fn__7445.invoke (main.clj:453)
    leiningen.core.main$_main.invokeStatic (main.clj:442)
    leiningen.core.main$_main.doInvoke (main.clj:439)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.core$apply.invokeStatic (core.clj:665)
    clojure.main$main_opt.invokeStatic (main.clj:491)
    clojure.main$main_opt.invoke (main.clj:487)
    clojure.main$main.invokeStatic (main.clj:598)
    clojure.main$main.doInvoke (main.clj:561)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.lang.Var.applyTo (Var.java:705)
    clojure.main.main (main.java:37)

My project.clj file:

(defproject yoco/sns2kafka "0.1.0-SNAPSHOT"
  :plugins [[reifyhealth/lein-git-down "0.4.0"]]
  :middleware [lein-git-down.plugin/inject-properties]
  :git-down {afrolabs/components {:coordinates Afrolabs/afrolabs-clj}}
  :repositories [["confluent" "https://packages.confluent.io/maven/"]
                 ["github" "git://github.com" :protocol :https]]
  :dependencies [[afrolabs/components "1c00e089b9933b68b081b886124f1754ece1de35"]

                 ;; json-schema validation https://github.com/juxt/jinx
                 [jinx "0.1.6" :exclusions [cljs-node-io]]
                 ]
  :aot [yoco.sns2kafka.core]
  :main yoco.sns2kafka.core
  :uberjar-name "yoco-sns2kafka.jar"
  :repl-options {:init-ns yoco.sns2kafka.core}
  :jvm-opts ["-XX:-OmitStackTraceInFastThrow"]
  :dev {:resource-paths ["dev-resources"]
        :source-paths ["test"]}
  )

The lein-git-down might be a funny or unusual configuration.

Environment & Version information

CIDER version information

I can't start the cider repl, so can't give this exactly output. I think these are my versions based on what's in the *Messages* buffer:

  • cider cider-20211221.1935
  • I run spacemacs

Lein/Boot version

  • Leiningen 2.9.3 on Java 16.0.1 OpenJDK 64-Bit Server VM

Emacs version

  • GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.20, cairo version 1.16.0) of 2020-09-19

Operating system

  • Ubuntu 20.04.3 LTS

Yeah, we enabled enrich-classpath only yesterday - basically it fetches automatically Java sources and sets up your classpath properly so you can navigate to them. You can set cider-enrich-classpath to nil to disable this while we figure out what's wrong.

If there something special about the way you run CIDER? I was under the impression that in most cases the creation of the additional cache folders wouldn't be an issue, but it seems in your cases some permissions are more restrictive than we expected. @vemv Probably there should be some permission check and just a warning if enrich can't do what it's supposed to do? Or maybe it can use /tmp instead, which would be wasteful but at least would work.

| You can set cider-enrich-classpath to nil to disable this while we figure out what's wrong.

Thank you for the work-around suggestion.

| If there something special about the way you run CIDER?

Not as far as I can tell, doing plain cider-jack-in...

AFAIK, the lein-git-down is the only "funny" thing in that project...

vemv commented

Note that the stacktrace doesn't have enrich-classpath anywhere in it.

Looking at the stracktrace, I have no idea of what Lein is doing there and how does it relate to anything that enrich-classpath does.

I'll create an issue in the Lein tracker.

vemv commented

@pieterbreed : does the issue persist if you comment out :middleware [lein-git-down.plugin/inject-properties]?

Likewise, is the issue exhibited in a new, minimal project?

Your feedback would be very valuable ๐Ÿ™

I created a new leiningen project with
lein new app testi
Then navigated to testi/src/testi/core.clj and did cider-jack-in and got the same error as OP.
Up to date Arch linux
openjdk version "11.0.13" 2021-10-19
OpenJDK Runtime Environment (build 11.0.13+8)
Leiningen 2.9.8 on Java 11.0.13 OpenJDK 64-Bit Server VM
GNU Emacs 28.0.90 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.30, cairo version 1.17.4)
of 2021-12-14
(this is native-compiled gtk build, running natively on Wayland)
Emacs packages loaded from Melpa and up to date

vemv commented

I've created technomancy/leiningen#2778 which can help us progress if not solving the issue entirely

@pieterbreed : does the issue persist if you comment out :middleware [lein-git-down.plugin/inject-properties]?

Likewise, is the issue exhibited in a new, minimal project?

Your feedback would be very valuable ๐Ÿ™

I commented out as per your suggestion, made no difference, still crashed with the same stacktrace. I tried with a different, much simpler project, same symptom.

Btw, this work with refactor-nrepl? I'm really wondering what's the difference in our setups, as for me enrich-classpath works fine on Ubuntu 20.04.

vemv commented

I'm really wondering what's the difference in our setups

Exactly, no clues so far

I use refactor-nrepl latest and enrich-classpath daily. enrich-classpath also enjoys an extensive CI matrix across OS and ~20 real-world projects.

So yeah this issue caught me very much by surprise!

It's disabled now from CIDER 1.2, let's see what we can do in the meantime.

The issue appears to be with the enrich middleware introducing empty paths in the project's :resource-path when no jdk sources are found and could depend on the jdk version, I submitted a PR hack to work around this clojure-emacs/enrich-classpath#13.

Can confirm that setting cider-enrich-classpath to nil clears the problem in the short term. Hit the same problem on a clean install of fedora 35, openjdk 17. Thanks for the quick action on this.

vemv commented

Cheers, yes we are happy with disabling enrich-classpath for a few weeks as done in CIDER 1.2.

@ikappaki has indeed found a good lead.

People affected by the issue in the thread, if you'd have a couple minutes could you please check if there's a file named src.zip somewhere (within any depth) of your Java home dir, namely (System/getProperty "java.home")?

You can find it with find or maybe a GUI file explorer. @pieterbreed @766 @lachlanh

(If you don't find it, please post your exact JDK, OS and how did you install said JDK ๐Ÿ™ )

In most OSes the JDK sources are a separate package. I guess it's easy to guess that we installed them, but many people didn't. :-)

vemv commented

That solves the mistery then :)

Fix incoming

@vemv was not able to find src.zip in 'java.home'
jdk : java-17-openjdk-17.0.1.0.12-2.rolling.fc35.aarch64
os : Fedora Workstation 35 for aarch64 (5.15.10-200.fc35.aarch64)
jdk installed with dnf install java-latest-openjdk and then selected with alternatives --config java. It was a clean vm install of os without alot of other stuff.

For Fedora you'll need to do something like:

$ sudo dnf install java-17-openjdk-src java-17-openjdk-javadoc

Afterwards everything should work properly, at least in theory.

Btw, it also seems that the sources are bundled with the JDKs for Windows and macOS, so only Linux users will need some additional setup. I've reflected this in the docs.