JuliaLS fails to start in neovim (and Jupyter)

Hello. I am using neovim mostly for coding in julia. Sadly, the julia LSP does not work. Every time I open a julia file I get the message “Client X quit with exit code 1 and signal 0”, and the LSP is dead. I have searched the Internet far and wide and spend way too much time trying to fix this, but so far have found no solution that worked.
This is inherently a difficult problem to post because it involves two complicated pieces of software (LangjuageServer.jl and neovim) trying to communicate. I already posted this question at the neovim discourse (here), but nobody over there seems to know whats wrong. Because LSP’s for other languages work (tested for lua, python, haskell) I assume it is a problem with julials specifically, thus I hope someone here might be able to help me.

My setup

  • Ubuntu 23.04
  • Neovim 0.9.1 (snap store)
  • Julia 1.9.3 (snap store)
  • LanguageServer.jl 4.4.0
  • nvim Config: personalized setup based on kickstart. Irrelevant to the problem, I suspect (see below)

What I have tried so far

  • reading most of neovim + LangugeServer thread
  • updating node, npm
  • uninstalling nvim, deleting all of
    • .cache/nvim
    • .config/nvim
    • .local/share/nvim
    • reinstalling nvim, downloading kickstart.nvim, installing julials via Mason
  • installing a fresh sandbox Ubuntu on a usb stick, installing only nvim, julia, gcc and kickstart.nvim

The problem persisted with all of the above

More details

I do not think that my nvim config itself is the problem, because a) the exact same setup on a different machine (running windows) works fine, and b) switching out my config for plain kickstart.nvim changed nothing. Let me know if you think otherwise.
Interestingly, I know that the JuliaLS is installed and functioning correctly too, because if I start Jupyter and open a cell via firenvim, the juliaLSP starts and works just fine (and downloads the entire symbol cache for each cell). But upon opening a regular .jl file the LSP immediatly dies.
Neovim has a logfile where errors from it’s LSPs are recorded, but I checked and the dying clients leave no trace there.(But the running LSPs from firenvim send all of their status updates like ‘downloading symbol cache …’ as errors to the logfile for some reason).
The LSP of Jupyter itself (not neovims LSP through firenvim) also has trouble with julials, but at least it is a little more informative about what is going on. The error messages of julials appear in the jupyter console, I have pasted some at the end of this text.

Given the above (works on windows and jupyter cells, plus the error messages of jupyter) I suspect the LSP starts up, tries to scan my project/directory and then somehow crashes. I have tried for many weeks now to fix this but nothing appears to help so far. Any help about what is wrong or where to look next is welcome.

Additional Info

The Jupyter console prints one error messagefor julials at the beginning of the session and then more error messages for every edit

initial Jupyter error message
[ Info: Downloading caches...
ERROR: Relative path `./Project.toml` is not valid.       ]  0.0 %
   Downloading [========================================>]  100.0 %>]  100.0 %
    error(s::String)
  @ Base ./error.jl:35
[2] filepath2uri(path::String)
  @ LanguageServer.URIs2 ~/.julia/packages/LanguageServer/ad2Yz/src/URIs2/uri_helpers.jl:32
[3] initialized_notification(params::LanguageServer.InitializedParams, server::LanguageServerInstance, conn::JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint})
  @ LanguageServer ~/.julia/packages/LanguageServer/ad2Yz/src/requests/init.jl:201
[4] (::LanguageServer.var"#111#112"{typeof(LanguageServer.initialized_notification), LanguageServerInstance})(conn::JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint}, params::LanguageServer.InitializedParams)
  @ LanguageServer ~/.julia/packages/LanguageServer/ad2Yz/src/languageserverinstance.jl:267
[5] dispatch_msg(x::JSONRPC.JSONRPCEndpoint{Base.PipeEndpoint, Base.PipeEndpoint}, dispatcher::JSONRPC.MsgDispatcher, msg::Dict{String, Any})
  @ JSONRPC ~/.julia/packages/JSONRPC/Q0FBr/src/typed.jl:67
[6] run(server::LanguageServerInstance)
  @ LanguageServer ~/.julia/packages/LanguageServer/ad2Yz/src/languageserverinstance.jl:387
[7] runserver(pipe_in::Base.PipeEndpoint, pipe_out::Base.PipeEndpoint, env_path::String, depot_path::String, err_handler::Nothing, symserver_store_path::Nothing)
  @ LanguageServer ~/.julia/packages/LanguageServer/ad2Yz/src/runserver.jl:41
[8] runserver()
  @ LanguageServer ~/.julia/packages/LanguageServer/ad2Yz/src/runserver.jl:39
[9] top-level scope
  @ none:1

recurring Jupyter error message
<LspStdIoWriter(parent=<LanguageServerSession(language_server=julia-language-server, argv=['/snap/bin/julia', '--project=.', '-e', 'using LanguageServer, LanguageServer.SymbolServer; runserver()', '.'])>)> couldn't write message: Content-Length: 193
  
  {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"file:///home/almighty-admin/.virtual_documents/Untitled4.ipynb","languageId":"julia","text":"\n","version":0}}}
  Traceback (most recent call last):
    File "/home/almighty-admin/anaconda3/lib/python3.10/site-packages/jupyter_lsp/stdio.py", line 193, in write
      await convert_yielded(self._write_one(response.encode("utf-8")))
    File "/home/almighty-admin/anaconda3/lib/python3.10/concurrent/futures/thread.py", line 58, in run
      result = self.fn(*self.args, **self.kwargs)
    File "/home/almighty-admin/anaconda3/lib/python3.10/site-packages/jupyter_lsp/stdio.py", line 201, in _write_one
      self.stream.write(message)
  BrokenPipeError: [Errno 32] Broken pipe
[E 2023-10-08 18:35:42.337 ServerApp] <LspStdIoWriter(parent=<LanguageServerSession(language_server=julia-language-server, argv=['/snap/bin/julia', '--project=.', '-e', 'using LanguageServer, LanguageServer.SymbolServer; runserver()', '.'])>)> couldn't write message: Content-Length: 195
  
  {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"file:///home/almighty-admin/.virtual_documents/Untitled4.ipynb","version":0},"contentChanges":[{"text":"\n"}]}}
  Traceback (most recent call last):
    File "/home/almighty-admin/anaconda3/lib/python3.10/site-packages/jupyter_lsp/stdio.py", line 193, in write
      await convert_yielded(self._write_one(response.encode("utf-8")))
    File "/home/almighty-admin/anaconda3/lib/python3.10/concurrent/futures/thread.py", line 58, in run
      result = self.fn(*self.args, **self.kwargs)
    File "/home/almighty-admin/anaconda3/lib/python3.10/site-packages/jupyter_lsp/stdio.py", line 201, in _write_one
      self.stream.write(message)

Here is the content of the files that as far as I know are responsible for starting julials in neovim. They are found in .local/share/nvim/mason/packages/julia-lsp/lebexec/bin/

julia-lsp
  #!/usr/bin/env bash

function help {
    cat <<EOF
Usage: julia-lsp <julia-env-path>
EOF
}

if [[ -z $1 ]]; then
    help
    exit 1
fi

set -euo pipefail

declare PKG_ROOT
if [[ $(uname -s) == Darwin ]]; then
    PKG_ROOT=$(perl -e "use File::Basename; use Cwd qw(abs_path); print(dirname(dirname(abs_path('$0'))))")
else
    PKG_ROOT=$(dirname "$(dirname "$(realpath "$0")")")
fi

# main.jl args
export JULIA_ENVIRONMENT_PATH="~/Documents/GitHub/texthopper"
export DEBUG="--debug=no"
export IGNORE_TELEMETRY_CRASH=""
export OLD_DEPOT_PATH=${JULIA_DEPOT_PATH:-""}
export STORAGE_PATH="${JULIA_LSP_STORAGE:-${PKG_ROOT}/store}"
if [[ ${SYMBOL_CACHE_DOWNLOAD:-1} != 0 ]]; then
    export USE_SYMSERVER_DOWNLOADS="download"
else
    export USE_SYMSERVER_DOWNLOADS="local"
fi
export SYMSERVER_UPSTREAM="${SYMBOL_SERVER:-https://www.julia-vscode.org/symbolcache}"
export DETACHED="--detached=no"

export JULIA_LOAD_PATH=":"
export JULIA_DEPOT_PATH="${PKG_ROOT}/store/lsdepot/v1"

: ${JULIA_LSP_JULIA_BIN:=julia}
exec "$JULIA_LSP_JULIA_BIN" --startup-file=no --history-file=no --depwarn=no "${PKG_ROOT}/extension/scripts/languageserver/main.jl" "$JULIA_ENVIRONMENT_PATH" "$DEBUG" "$IGNORE_TELEMETRY_CRASH" "$OLD_DEPOT_PATH" "$STORAGE_PATH" "$USE_SYMSERVER_DOWNLOADS" "$SYMSERVER_UPSTREAM" "$DETACHED"
julia-lsp.cmd
  @echo off
echo "hello"
set "PKG_ROOT=%~dp0.."

rem main.jl args
set "JULIA_ENVIRONMENT_PATH=%1"
set "DEBUG=--debug=no"
set "IGNORE_TELEMETRY_CRASH="
set "OLD_DEPOT_PATH=%JULIA_DEPOT_PATH%"
IF "%JULIA_LSP_STORAGE%"=="" (
    set "STORAGE_PATH=%PKG_ROOT%\store"
) ELSE (
    set "STORAGE_PATH=%JULIA_LSP_STORAGE%"
)
IF "%SYMBOL_CACHE_DOWNLOAD%"=="0" (
    set "USE_SYMSERVER_DOWNLOADS=local"
) ELSE (
    set "USE_SYMSERVER_DOWNLOADS=download"
)
IF "%SYMBOL_SERVER%"=="" (
    set "SYMSERVER_UPSTREAM=https://www.julia-vscode.org/symbolcache"
) ELSE (
    set "SYMSERVER_UPSTREAM=%SYMBOL_SERVER%"
)
IF "%JULIA_LSP_JULIA_BIN%"=="" (
    set "JULIA_LSP_JULIA_BIN=julia"
)

set "DETACHED=--detached=no"
set "JULIA_LOAD_PATH=;"
set "JULIA_DEPOT_PATH=%PKG_ROOT%\store\lsdepot\v1"

"%JULIA_LSP_JULIA_BIN%" --startup-file=no --history-file=no --depwarn=no "%PKG_ROOT%\extension\scripts\languageserver\main.jl" "%JULIA_ENVIRONMENT_PATH%" "%DEBUG%" "%IGNORE_TELEMETRY_CRASH%" "%OLD_DEPOT_PATH%" "%STORAGE_PATH%" "%USE_SYMSERVER_DOWNLOADS%" "%SYMSERVER_UPSTREAM%" "%DETACHED%"

Can you try not using Julia from the snap store? Can you install it from the official downloads or using juliaup?

3 Likes

I purged my snap store installation and installed juliaup

aaaand the LSP now just works. WTF? Why are the binaries from the official Ubuntu software repo incapable of hosting an LS? I even considered not mentioning this information in my summaries!

Anyway, thanks for the hint. This has really bothered me for quite a while.

1 Like

Glad to hear you got it fixed! I’ve had a lot of issues with outdated Ubuntu repos across countless development stacks.

juliaup is a really great way to sort of bypass a lot of the distro specific issues you get (like this!)

I still don’t quite get it. It might be that some apps on the snap store are outdated, but my julia binaries were just regular julia 1.9 binaries, so they are really not outdated. I used snap store julia for almost 1.5 years with absolutely no issues, scripting, package development, hosting jupyter kernels, everything worked as expected out of the box. And the source code for julials was installed (and many times purged and reinstalled) by Pkg.jl, so they should also be up to date.
But somehow when these snap store 1.9 binaries ran the same LanguageServer.jl code as my new juliaup 1.9 binaries are running now something went very different. My only explanation is that the snap store encircles its apps in some sort of local environment that the LS had trouble escaping from.

But whatever, I guess, its working now, and as a bonus juliaup is keeping my version up to date without me having to interfere, so I’m happy :person_shrugging:.