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.
| Content | Preserve through |
|---|---|
| Lua configuration and extras | Configuration repository |
| Plugin commits | lazy-lock.json |
| Editor and external tool versions | Environment/package records |
| Project dependencies | Project locks and toolchain files |
| Caches, logs and downloads | Tool-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
| Symptom | Entry point | Likely scope |
|---|---|---|
| Lua startup error | Messages and stack trace | Syntax, removed API, initialisation |
| Changed key behaviour | :verbose nmap | Global/local mappings and order |
| One language fails | LSP health and clients | Paths, roots, tool versions |
| Saving changes too much | ConformInfo and autocmds | Duplicate formatters or project rules |
| Plugin download fails | Lazy logs and network checks | DNS, Git, connectivity, concurrency |
| Large file is slow | File-size and plugin comparisons | Parsing, diagnostics, Git decoration, rendering |
Logs may contain paths or project text. Preserve diagnostic evidence without publishing unrelated data.
Reduce to a small environment
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:
It proves syntax, not module availability or API compatibility.
For an empty startup timing log:
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.