Neovim 0.12 Treesitter Migration

What happened

Neovim 0.12.0 ships with breaking changes to the treesitter API. The nvim-treesitter plugin was fully rewritten on a new main branch (the old master branch is frozen for Neovim 0.11 compatibility only).

The old master branch code calls node:range() on nodes that can now be nil in 0.12, causing cascading errors across plugins that depend on treesitter (render-markdown.nvim, nvim-treesitter-context, snacks.nvim, the treesitter highlighter itself).

What changed in the migration

  • nvim-treesitter: switched from master to main branch. The old require("nvim-treesitter.configs").setup() API no longer exists.
  • Highlight/indent/folding: now enabled via vim.treesitter builtins and FileType autocmds instead of plugin config tables.
  • nvim-treesitter-textobjects: also switched to main. Keymaps now use explicit vim.keymap.set calls instead of declarative config tables.
  • treesitter-context: API unchanged, just reorganized into the same plugin spec file.
  • Debug utilities: updated to use vim.treesitter.get_parser() instead of the removed nvim-treesitter.parsers module.

What was lost

  • Incremental selection (<C-Space> expand, <M-Space> shrink): removed from nvim-treesitter. Now built into Neovim 0.12 as an/in default mappings. Public API for custom remapping is still being discussed (neovim/neovim#38211).
  • Playground config: no longer part of the rewritten plugin.

Key lesson

When Lazy.nvim has a plugin cached on one branch, :Lazy update alone won’t switch branches. You need to delete the plugin directory (~/.local/share/nvim/lazy/nvim-treesitter) and restart so Lazy re-clones from the new branch.

References