Home Posts Notes About

Upgrading the nvim-treesitter plugin

October 17th, 2025 · #neovim #treesitter

Every couple of weeks, I run MiniDeps's :DepsUpdate and cross my fingers that everything is going to be fine. Most of the time it is but not this morning[1].

Immediately, I got the following errors:

Error detected while processing ~/.config/nvim/init.lua:
E5113: Error while calling lua chunk: ~/.config/nvim/lua/_/ui/treesitter.lua:1: module 'nvim-treesitter.configs' not found:
        no field package.preload['nvim-treesitter.configs']
        no file '/nix/store/w997z7g0ii6figi4z98id0b0yn2jzala-luajit-2.1.1741730670-env/share/lua/5.1/nvim-treesitter/configs.lua'
        no file '/nix/store/w997z7g0ii6figi4z98id0b0yn2jzala-luajit-2.1.1741730670-env/share/lua/5.1/nvim-treesitter/configs/init.lua'
        no file '/nix/store/bmdviv9ljgqb6siq2p3dsll497fjzpif-luajit2.1-fzy-1.0.3-1/share/lua/5.1/nvim-treesitter/configs.lua'
        no file '/nix/store/bmdviv9ljgqb6siq2p3dsll497fjzpif-luajit2.1-fzy-1.0.3-1/share/lua/5.1/nvim-treesitter/configs/init.lua'
        no file '/nix/store/w997z7g0ii6figi4z98id0b0yn2jzala-luajit-2.1.1741730670-env/lib/lua/5.1/nvim-treesitter/configs.so'
        no file '/nix/store/bmdviv9ljgqb6siq2p3dsll497fjzpif-luajit2.1-fzy-1.0.3-1/lib/lua/5.1/nvim-treesitter/configs.so'
        no file '/nix/store/w997z7g0ii6figi4z98id0b0yn2jzala-luajit-2.1.1741730670-env/lib/lua/5.1/nvim-treesitter.so'
        no file '/nix/store/bmdviv9ljgqb6siq2p3dsll497fjzpif-luajit2.1-fzy-1.0.3-1/lib/lua/5.1/nvim-treesitter.so'

Investigating further, I saw that the master branch of nvim-treesitter is now frozen and they're now working on the main branch. The new branch is a complete rewrite. The fix could have been a simple:

  MiniDeps.add({
    source = 'nvim-treesitter/nvim-treesitter',
-   checkout = 'master',
+   checkout = 'main',
    hooks = { post_checkout = function() vim.cmd('TSUpdate') end },
  })

However, since I was there and I figured I'll just do the update properly. First, my configuration looked like this:

local configs = require('nvim-treesitter.configs')
local mdx = require('mdx')

---@diagnostic disable-next-line: missing-fields
configs.setup({
  auto_install = true,
  highlight = { enable = true },
  endwise = { enable = true },
  indent = { enable = true },
})

The rewrite removes the need for manual config except for customization on where the parsers are installed. To keep the behaviours I had before, in my case, the auto_install option and the highlighting, I update my config like this:

  1. First, I installed parsers for files in my dotfile on startup. Thankfully, this is a no-op when they're already installed:
local ts = require('nvim-treesitter')

-- Wait at most 30 seconds to finish installation.
ts.install(
  {
    'lua', 'vim', 'vimdoc', 'query',
    'markdown', 'markdown_inline',
    'json', 'yaml',
  },
  -- Do not print summary, as this will run at startup always, all the time.
  { summary = false }
):wait(30000)
  1. Then, I install the parser and enable highlighting and other plugin using an autocmd that triggers on FileType:
---@type fun(args: vim.api.keyset.create_autocmd.callback_args): boolean?
local install_parser_and_enable_features = function(event)
  local lang = event.match

  -- Try to start the parser install for the language.
  local ok, task = pcall(ts.install, { lang }, { summary = true })
  if not ok then return end

  -- Wait for the installation to finish (up to 10 seconds).
  task:wait(10000)

  -- Enable syntax highlighting for the buffer
  ok, _ = pcall(vim.treesitter.start, event.buf, lang)
  if not ok then return end

  -- Enable other features as needed.

  -- Enable indentation based on treesitter for the buffer.
  -- vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"

  -- Enable folding based on treesitter for the buffer.
  -- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
end

-- Install missing parsers on file open.
vim.api.nvim_create_autocmd('FileType', {
  group = vim.api.nvim_create_augroup('ui.treesitter', { clear = true }),
  pattern = { '*' },
  callback = install_parser_and_enable_features
})

And like that, no more errors and treesitter works as expected. I should probably read more about the reasons of the rewrite, but I'll leave this for another Friday.


Footnotes

  1. You'd think after more than 15 years, I'd understand that Friday are not the days to be nonchalant about potentially breaking things. ↩︎

Mastodon