Pyright-langserver only works if I omit the 'root_dir' argument

Context: I am trying to learn how LSP works in neovim by creating the most basic config possible and not using any plugins. I’m running NVIM v0.11.0-dev-960+ge049c6e4c.

I have created a project directory under /home/elifast/lsp and used npm to install pyright into the local node_modules folder in that directory. I then run nvim --clean test.py to open a new nvim instance without any config at all.

Then I try running
:lua vim.lsp.start({ name = 'pyright', cmd = { 'npx', '--prefix', 'home/elifast/lsp', 'pyright-langserver', '--stdio' }, root_dir = vim.fn.getcwd() })
which does not work. I can try running :lua vim.lsp.buf.hover() and it behaves the same as if there were no LSP attached at all (although :checkhealth lsp indicates that the lsp is indeed attached.)

After some experimentation, I found that omitting the root_dir argument allows everything to work fine:
:lua vim.lsp.start({ name = 'pyright', cmd = { 'npx', '--prefix', 'home/elifast/lsp', 'pyright-langserver', '--stdio' } })

When I run
:lua print(vim.inspect(vim.lsp.get_clients()[1]))
In both situations, here are the differences:

diff --git a/lognotworking.txt b/logworking.txt
index 5e76667..86d400a 100644
--- a/lognotworking.txt
+++ b/logworking.txt
@@ -188,8 +188,7 @@
   commands = {},
   config = {
     cmd = { "npx", "--prefix", "home/elifast/lsp", "pyright-langserver", "--stdio" },
-    name = "pyright",
-    root_dir = "/home/elifast/lsp"
+    name = "pyright"
   },
   dynamic_capabilities = {
     capabilities = {},
@@ -240,14 +239,7 @@
   },
   request = <function 19>,
   request_sync = <function 20>,
-  requests = {
-    [2] = {
-      bufnr = 1,
-      method = "textDocument/hover",
-      type = "pending"
-    }
-  },
-  root_dir = "/home/elifast/lsp",
+  requests = {},
   rpc = {
     is_closing = <function 21>,
     notify = <function 22>,
@@ -323,10 +315,6 @@
   settings = {},
   stop = <function 25>,
   supports_method = <function 26>,
-  workspace_folders = { {
-      name = "/home/elifast/lsp",
-      uri = "file:///home/elifast/lsp"
-    } },
   <metatable> = <1>{
     __index = <table 1>,
     _add_workspace_folder = <function 27>,

After that, I tried running the initial experiment with a different language server.
with root_dir:
:lua vim.lsp.start({ name = 'html', cmd = { 'npx', '--prefix', '/home/elifast/lsp', 'vscode-html-language-server', '--stdio' }, root_dir = vim.fn.getcwd() })
and without:
:lua vim.lsp.start({ name = 'html', cmd = { 'npx', '--prefix', '/home/elifast/lsp', 'vscode-html-language-server', '--stdio' }})

And it worked as expected both times. So this seems to indicate that it is something to do with pyright specifically.

At this point I’ve run out of ideas for how to get more information. If anyone has any ideas on what the issue could be or advice on what to try next it would be much appreciated.

Thanks!

I had the same issue and spent hours banging my head against the wall to try to figure it out.

I JUST figured it out. On a whim, I copied in the config from lspconfig and it worked, despite not being very different from mine. I removed line by line until it stopped working, and I found the key seems to be the addition of settings = { python = { } }. Doesn’t make sense, but when I remove that bit it stops working unless I remove root_markers (an alternative way of specifying root_dir; added in nvim 0.12 I believe).

Here’s my working config (if you’re before nvim 0.12 you may need to translate to the older LSP setup syntax):

vim.lsp.config["pyright"] = {
    cmd = {"pyright-langserver", "--stdio"},
    filetypes = {"python"},
    root_markers = {
        "pyproject.toml",
        "setup.py",
        "setup.cfg",
        "requirements.txt",
        "Pipfile",
        "pyrightconfig.json",
        ".git"
    },
    settings = {
        python = {
        }
    },
}
vim.lsp.enable('pyright')

Hope this saves someone else some pain.

The way I fixed a similar issue was by using the function form for root_dir

root_dir = function(_bufnr, on_dir)
	on_dir(<your custom root_dir here)
end