This post explains the breaking changes introduced in Mason 2.0 and Mason-LSPConfig 2.0 and how to migrate Neovim LSP configurations. It includes updated configuration examples, a specific case for Vue LSP, and guidance on handling servers not available in Mason’s registry.
Mason v2.0 and Mason-LSPConfig v2.0 are finally out, and while the updates bring some solid improvements, they also introduced a few breaking changes that caused my Neovim LSP setup to stop working.
In this post, I’ll go over what changed, what broke for me, and how I updated my config to work with the new versions. I’ll also walk through a Vue-specific setup using Volar
and how to handle language servers not yet available in the Mason registry.
With the arrival of Mason 2.0 and Mason-LSPConfig 2.0, a few core things have shifted:
Mason 2.0 now requires Neovim >= 0.10, and Mason-LSPConfig 2.0 requires Neovim >= 0.11.
get_install_path()
is goneIn previous versions, it was common to grab the install path for a package like this:
local mason_registry = require("mason-registry")
local path = mason_registry.get_package("lua-language-server"):get_install_path()
That no longer works in Mason 2.0 as get_install_path()
has been removed. Now you're encouraged to rely on:
PATH
)$MASON
env var: vim.fn.expand("$MASON/packages/<package-name>")
to get the install directory manuallysetup_handlers
is gone tooIf you used something like this in your config:
mason_lspconfig.setup_handlers {
["lua_ls"] = function() ... end
}
That won’t work anymore. The handlers
callback and automatic_installation
options are gone. Mason-LSPConfig now automatically enables installed servers by default (unless you disable that), and you're expected to configure servers directly via lspconfig
or the new vim.lsp.config()
API (introduced in v0.11).
Here’s what my updated setup looks like now:
-- 1. Initialize Mason (v2.0+)
require("mason").setup()
-- 2. Initialize Mason-LSPConfig with my servers
require('mason-lspconfig').setup({
ensure_installed = {
'lua_ls',
'tailwindcss',
'volar',
'ts_ls',
'rust_analyzer',
'gopls',
'clangd',
'jdtls',
},
automatic_enable = true, -- Mason-LSPConfig v2 auto-enables servers by default
})
-- 3. Configure LSP servers
-- All clients
vim.lsp.config('*', {
-- any custom settings...
})
-- Lua (lua-language-server)
vim.lsp.config('lua_ls', {
settings = {
Lua = {
runtime = { version = 'Lua 5.1' },
diagnostics = {
globals = { 'bit', 'vim', 'it', 'describe', 'before_each', 'after_each' },
},
},
},
})
-- TypeScript / JavaScript (ts_ls)
vim.lsp.config('ts_ls', {
-- any custom settings...
})
Now I typically do one of two things:
vim.lsp.config("server_name", {...})
to configure a server (this is my preferred approach).require("lspconfig").<server>.setup({})
as before, since LSPConfig now delegates to vim.lsp
, and it's enabled by default.Some language servers, like GDScript, aren’t included in the Mason registry. If you try to add them to ensure_installed
, Mason will complain. In that case, you just set them up manually like this:
require("lspconfig").gdscript.setup({
cmd = { "gdscript-language-server", "--stdio" },
})
In my previous setup, I used get_install_path()
to find the plugin path for Volar’s TypeScript integration. Since that’s gone, here’s how I do it now:
-- Ensure 'vue-language-server' is installed via Mason (e.g. add "volar" above)
-- Then, manually locate the Volar plugin path:
local vue_ls_path = vim.fn.expand("$MASON/packages/vue-language-server")
local vue_plugin_path = vue_ls_path .. "/node_modules/@vue/language-server"
-- Now configure ts_ls (TypeScript) to load the Vue plugin
require("lspconfig").ts_ls.setup({
init_options = {
plugins = {
{
name = "@vue/typescript-plugin",
location = vue_plugin_path,
languages = { "vue" },
},
},
},
filetypes = { "typescript", "javascript", "vue" },
})
The init_options.plugins
block loads the Vue TS plugin for .vue
files.
The 2.0 releases of Mason and Mason-LSPConfig introduced some real improvements, but they also required a few config changes to keep things working smoothly. If your LSP setup broke after updating, hopefully this post helps get you back on track.
Just remember: no more get_install_path()
or setup_handlers()
. The new APIs are simpler and more native to Neovim’s evolution.