I am currently playing around with Neovim and ElixirLS.
I have two very similar Phoenix projects, but the ElixirLS integration only works for one of them and I can't figure out what is the reason, especially because I don't know where the error originates from.
Here's my nvim-lspconfig
configuration for Elixir:
return {
"neovim/nvim-lspconfig",
config = function()
local lspconfig = require("lspconfig")
lspconfig.elixirls.setup({
cmd = { "elixir-ls" },
on_attach = function(client, buffer)
vim.api.nvim_create_autocmd("BufWritePre", {
buffer = buffer,
callback = function()
vim.lsp.buf.format({ async = false })
end
})
end,
elixirLS = {
dialyzerEnabled = false,
fetchDeps = false
}
})
end
}
For debugging purposes I check ~/.local/state/nvim/lsp.log
to see what is going on. When opening an elixir file of project A, I get the following log messages:
[[START][2025-07-17 16:24:26] LSP logging initiated
[ERROR][2025-07-17 16:24:26] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Running /home/jan/.asdf/installs/elixir-ls/0.28.0/launch.sh\n"
[ERROR][2025-07-17 16:24:26] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Preferred shell is bash, relaunching\n"
[ERROR][2025-07-17 16:24:26] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Looking for asdf install\n"
[ERROR][2025-07-17 16:24:26] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "asdf executable found at /home/jan/.asdf/bin/asdf. Using ASDF_DIR=, ASDF_DATA_DIR=/home/jan/.asdf.\n"
[ERROR][2025-07-17 16:24:26] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Installing ElixirLS release v0.28.0\nRunning in /home/jan/Workspace/project-a\n"
[ERROR][2025-07-17 16:24:26] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Install complete\n"
I do the same for project B:
[START][2025-07-17 16:25:43] LSP logging initiated
[ERROR][2025-07-17 16:25:43] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Running /home/jan/.asdf/installs/elixir-ls/0.28.0/launch.sh\nPreferred shell is bash, relaunching\nLooking for asdf install\n"
[ERROR][2025-07-17 16:25:43] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "asdf executable found at /home/jan/.asdf/bin/asdf. Using ASDF_DIR=, ASDF_DATA_DIR=/home/jan/.asdf.\n"
[ERROR][2025-07-17 16:25:43] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Installing ElixirLS release v0.28.0\n"
[ERROR][2025-07-17 16:25:43] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Running in /home/jan/Workspace/project-b\n"
[ERROR][2025-07-17 16:25:43] ...p/_transport.lua:36 "rpc" "elixir-ls" "stderr" "Install complete\n"
So far so good, everything looks good. When I now edit a file in project A and save it, the file gets formatted and I only get some output about elixir warnings from dependencies:
[WARN][2025-07-17 16:27:50] ...lsp/handlers.lua:564 " warning: <%# is deprecated, use <%!-- or add a space between <% and # instead\n │\n 1 │ <%#\n │ ~\n │\n └─ lib/event_store/sql/statements/insert_events.sql.eex:1: (file)\n"
[WARN][2025-07-17 16:27:50] ...lsp/handlers.lua:564 " warning: <%# is deprecated, use <%!-- or add a space between <% and # instead\n │\n 24 │ <%#\n │ ~\n │\n └─ lib/event_store/sql/statements/insert_events.sql.eex:24: (file)\n"
[WARN][2025-07-17 16:28:15] ...lsp/handlers.lua:564 " warning: redefining module Mix.Tasks.Dialyzer (current version loaded from /home/jan/.cache/mix/installs/elixir-1.18.3-erts-15.2.3/fbaa1690847ff8f7acc189fd105b76b0/_build/prod/lib/dialyxir_vendored/ebin/Elixir.Mix.Tasks.Dialyzer.beam)\n │\n 1 │ defmodule Mix.Tasks.Dialyzer do\n │ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n │\n └─ lib/mix/tasks/dialyzer.ex:1: Mix.Tasks.Dialyzer (module)\n"
When I do the same in project B, editing a file and saving it, I only get this:
[ERROR][2025-07-17 16:29:16] ...m/lsp/client.lua:619 "LSP[elixirls]" "Cannot find request with id 2 whilst attempting to cancel"
The file is save, but not formatted. I already figured out that this message comes from the LSP client in Neovim: https://github.com/neovim/neovim/blob/e6ce067f02ed07501093e79dc56466fada8652a1/runtime/lua/vim/lsp/client.lua#L663
I think it's only a sympton, not the root cause, but the .elixir_ls
directory in project B is empty whereas it contains a build directory for project A:
$ ls -la project-a/.elixir_ls
total 12M
drwxrwxr-x 3 jan jan 4,0K Jul 17 16:27 build
-rw-rw-r-- 1 jan jan 1 Jul 17 16:27 .gitignore
-rw-rw-r-- 1 jan jan 12M Jul 17 16:31 iplt-27.3_elixir-1.18.3-test
$ ls -la project-b/.elixir_ls
total 4,0K
-rw-rw-r-- 1 jan jan 1 Jul 7 07:31 .gitignore
Both projects use the same Elixir and Erlang versions:
$ cat .tool-versions
erlang 27.3
elixir 1.18.3-otp-27
Here's my Neovim version:
$ nvim --version
NVIM v0.11.2
Build type: Release
LuaJIT 2.1.1741730670
Run "nvim -V1 -v" for more info
Does anyone have any clue why everything works fine for project-a, but doesn't for project-b?
Edit: I just realized that when I open up a file from project B in the same Neovim instance where I have project A, everthing works just fine. I thinks that's an important information for you. I open up Neovim for each project.
Terminal A:
$ nvim lib/project_a_web/router.ex
Terminal B:
$ nvim lib/project_b_web/router.ex
I finally found the root cause for ElixirLS not working for the existing project.
$ MIX_ENV=test iex -S mix
Erlang/OTP 27 [erts-15.2.3] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]
** (File.Error) could not read file "/home/jan/Workspace/project-b/config/test.exs": no such file or directory
I renamed test
for that project, but ElixirLS requires it. Adding config/test.exs
solved the issue for me.