Neovim versions, upgrades and fault isolation

On this page

An update can affect Neovim, LazyVim, plugins, parsers, language servers and SDKs. Updating everything together makes attribution difficult. Record versions and verify one layer at a time.

What the lockfile controls

lazy-lock.json pins plugin commits. It does not pin the Neovim binary, every Mason tool, system SDKs or project dependencies.

ContentPreserve through
Lua configuration and extrasConfiguration repository
Plugin commitslazy-lock.json
Editor and external tool versionsEnvironment/package records
Project dependenciesProject locks and toolchain files
Caches, logs and downloadsTool-specific rebuilding rather than handwritten configuration

See lazy.nvim lockfiles.

Establish an upgrade baseline

Save buffers and explain any uncommitted configuration changes. Record nvim --version and the lockfile, then choose a familiar small project.

Test file opening, project search, definition lookup, formatting, tests, input methods and clipboard. Include a Zellij boundary test if used daily. Upgrade only from a known working baseline, read relevant release notes and inspect pending changes in :Lazy.

Repeat the same tasks afterwards. Successful startup alone does not establish working language services or unchanged bindings.

Select checks from the symptom

SymptomEntry pointLikely scope
Lua startup errorMessages and stack traceSyntax, removed API, initialisation
Changed key behaviour:verbose nmapGlobal/local mappings and order
One language failsLSP health and clientsPaths, roots, tool versions
Saving changes too muchConformInfo and autocmdsDuplicate formatters or project rules
Plugin download failsLazy logs and network checksDNS, Git, connectivity, concurrency
Large file is slowFile-size and plugin comparisonsParsing, diagnostics, Git decoration, rendering

Logs may contain paths or project text. Preserve diagnostic evidence without publishing unrelated data.

Reduce to a small environment

nvim --clean notes.md

If the problem remains, inspect the terminal, input method or Neovim itself. If it disappears, add required plugins in a separate NVIM_APPNAME setup. Do not delete daily configuration and data to isolate a fault.

This compiles a Lua file without executing its contents; run it from the intended configuration directory:

nvim --clean --headless '+lua assert(loadfile("init.lua"))' +qa

It proves syntax, not module availability or API compatibility.

For an empty startup timing log:

nvim --startuptime /tmp/nvim-startup.log +qa

Avoid private file contents in measurements. Cache and network conditions affect timing; locate an expensive phase before changing load events.

Restore a known working state

Preserve the failing configuration and logs. Restore known-good Lua and lockfile content from Git, then use :Lazy restore to restore plugin commits. Restart and rerun baseline tasks.

A plugin restore cannot downgrade Neovim or external language servers. Recover those through their own package or toolchain mechanisms when responsible.

Deleting data, state and cache indiscriminately can remove useful logs and history without addressing the cause.

Keep local adaptations maintainable

Prefer public options in plugin specifications. For an internal-function override, record the plugin commit, reproduced trigger, upstream issue and removal condition.

The older smart-splits boundary-probe override illustrates this: local configuration retained a workaround even though the installed implementation now returns a fixed result. Review whether such patches remain necessary during upgrades.

Finish maintenance with a verified configuration and a short record explaining changed versions and recovery.