Tree-sitter migration guide for Neovim 0.12

April 2, 2026


Neovim recently updated to 0.12 with major improvements to the built-in LSP client and better terminal handling among other nice things.

This update broke my setup. Opening Neovim afterwards showed a wall of attempt to call method 'start' (a nil value) error from nvim-treesitter along with a full stack trace. No syntax highlighting, no textobjects, nothing worked.

What is treesitter?

Treesitter helps Neovim and other IDEs like VSCode understand the structure of the code. Many code editor features like highlighting, indentation, and code folding are powered by the treesitter parsers.

To nerd out a bit, treesitter builds a concrete syntax tree (CST) of the source code behind the scenes and lets plugins query that tree to power features like syntax highlighting, indentation, etc. The CST is roughly similar to the DOM tree for HTML, both being structured representations of the underlying text.

The tree-sitter docs has a cool playground that lets you see the syntax tree for a piece of code in real time.

What to change in nvim-treesitter

Neovim bundles the treesitter runtime, but most people use the nvim-treesitter plugin to manage parser installation and configuration.

That plugin got a full rewrite on a new main branch. The old master branch is frozen and won't work with Neovim 0.12.

1. Install the tree-sitter CLI

The new nvim-treesitter compiles parsers locally and depends on the tree-sitter CLI. The old version bundled everything. The new one doesn't so we have to install it manually.

2. Reinstall the plugin

These code examples reflect my lazy.nvim plugin manager. Adjust for your plugin manager if you use something else.

The default branch changed from master to main. lazy.nvim caches the branch it originally cloned, so you need to remove and reinstall the plugin. Find nvim-treesitter in the lazy.nvim UI, press X to remove it, then restart Neovim.

Also remove branch = 'master' if you had it set explicitly:

{
  'nvim-treesitter/nvim-treesitter',
  branch = 'master', 
  ...
},

3. Fix the module name

The old config module nvim-treesitter.configs no longer exists. The new plugin exports setup() from the top-level nvim-treesitter module. If you have a main field in your lazy.nvim spec, update it:

main = 'nvim-treesitter.configs', 
main = 'nvim-treesitter', 

4. Replace ensure_installed

ensure_installed is no longer a config option. It silently does nothing. You call the install API yourself instead. Here's an init callback that diffs against already-installed parsers so it doesn't reinstall everything on every startup:

init = function()
  local ensureInstalled = {
    'lua', 'python', 'typescript',
    -- ... your parsers
  }
  local alreadyInstalled = require('nvim-treesitter.config').get_installed()
  local parsersToInstall = vim.iter(ensureInstalled)
    :filter(function(parser)
      return not vim.tbl_contains(alreadyInstalled, parser)
    end)
    :totable()
  require('nvim-treesitter').install(parsersToInstall)
end,

Textobjects (optional)

If you use nvim-treesitter-textobjects, same story. You need its main branch too:

{
  'nvim-treesitter/nvim-treesitter-textobjects',
  branch = 'main', 
  ...
}

Last steps

  1. :Lazy update nvim-treesitter to pull the new main branch
  2. :TSUninstall all to remove old parsers compiled by the master branch
  3. Restart Neovim
  4. :TSUpdate to rebuild parsers with the new compiler
  5. :checkhealth nvim-treesitter to make sure everything's wired up