Breaking Changes in Mason 2.0: How I Updated My Neovim LSP Config

2025-05-07 74 +1

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.

# Breaking Changes in Mason 2.0: How I Updated My Neovim LSP Config

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.

## What’s changed?

With the arrival of Mason 2.0 and Mason-LSPConfig 2.0, a few core things have shifted:

### Minimum versions required

Mason 2.0 now requires Neovim >= 0.10, and Mason-LSPConfig 2.0 requires Neovim >= 0.11.

### get_install_path() is gone

In 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:

  • Just the executable name (Mason adds them to your PATH)
  • Or use the $MASON env var: vim.fn.expand("$MASON/packages/<package-name>") to get the install directory manually

### setup_handlers is gone too

If 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).

## Updating the config

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:

  • Use vim.lsp.config("server_name", {...}) to configure a server (this is my preferred approach).
  • Or just use require("lspconfig").<server>.setup({}) as before, since LSPConfig now delegates to vim.lsp, and it's enabled by default.

## What about servers not in the registry?

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" },
})

## Vue LSP (Volar) plugin path

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.

## Conclusion

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.

All posts

kosu.me 🐧 - 2024