Search code examples
javapowershellclojurepath-variables

Trying to run a clojure project on emacs but Java error: Cannot run program powershell.exe


I am trying to run a clojure jar file on emacs using cider and I get the error below:

ERROR:ERROR:  Unhandled REPL handler exception processing messageUnhandled REPL handler exception processing message  {{:op:op  init-debuggereval, , :code cljs.core/demunge, :session 9f9a0db9-8cc7-4cf0-b0ba-f426b163fb52, :id :nrepl.middleware.print/stream?7 }1
, :nrepl.middleware.print/print cider.nrepl.pprint/pprint, :nrepl.middleware.print/quota 1048576, :nrepl.middleware.print/buffer-size 4096, :nrepl.middleware.print/options {:right-margin 70}, :session 2f97cb2f-b111-4c37-8658-b63045c9ab2a, :id 6}
Syntax error macroexpanding at (clojuredocs.clj:19:32).

Caused by: java.io.IOException: Cannot run program "powershell.exe": CreateProcess error=2, The system cannot find the file specified

I have powershell route set on my env PATH both on System envs and User envs as follow:

enter image description here

Java version: "20.0.1"

I am not sure what I am missing to be able to run the command cider-jack-in successfully


Solution

  • Mathias R. Jessen provided the crucial pointer in a comment:

    The special PATH[1] environment variable (accessible in PowerShell at the process level as $env:PATH - see the conceptual about_Environment_Variables help topic) - on both Windows and Unix-like platforms - contains a list of (usually absolute) directory paths in which the platform APIs look for executables when an attempt is made to invoke an executable by file name only (rather than, unambiguously, by a file path).

    • Therefore, it is never the path of a given executable file itself that should be added to that list, but only ever the directory in which that executable is located.

    General information:

    • The separator character used to separate the PATH entries is platform-specific:

      • Windows uses ;, whereas Unix-like platforms use :
      • To programmatically determine this character, use [System.IO.Path]::PathSeparator
    • The order of entries matters: the first directory listed in which an executable of the given name is found is used.

      • Additionally, on Windows only, if a name doesn't include a filename extension (e.g., just foo instead of foo.exe), Windows tries the extensions listed in the special PATHEXT in order to find a matching executable (on Unix, executables usually do not have extensions, and if they do, they must be specified explicitly).
    • PowerShell itself has no support for programmatically modifying the persistent definition of PATH, necessitating direct use of the [System.Environment]::SetEnvironmentVariable() .NET API:

      • However:
        • (a) This API works on Windows only (there is no unified mechanism that would work across all Unix-like platforms)
        • (b) This API isn't robust, because it invariably converts the REG_EXPAND_SZ PATH definition to REG_SZ
      • See this answer for background information and a registry-based workaround.

    [1] The exact case on Windows is Path, whereas on Unix-like platforms it is PATH. Since environment-variable access in Windows is case-insensitive, whereas on Unix it is case-sensitive, the form PATH works on both platforms.