Skip to content

fix(manage): don't overwrite lockfile when lockfile=true#2127

Open
OleksandrChekhovskyi wants to merge 1 commit into
folke:mainfrom
OleksandrChekhovskyi:fix/lockfile-preserve-on-install
Open

fix(manage): don't overwrite lockfile when lockfile=true#2127
OleksandrChekhovskyi wants to merge 1 commit into
folke:mainfrom
OleksandrChekhovskyi:fix/lockfile-preserve-on-install

Conversation

@OleksandrChekhovskyi
Copy link
Copy Markdown

Summary

When opts.lockfile is true, skip the lock.update() call after install() and update(). This is a two-line change.

The problem

lock.update() rewrites the entire lazy-lock.json from the current on-disk state of all installed plugins — not just the ones touched by the current operation. This means that even when lockfile=true correctly checks out pinned versions for the target plugins, the lockfile gets overwritten with whatever commits all other plugins happen to be at.

This affects two code paths:

  1. Startup auto-install (install.missing) — loader.lua calls install({ lockfile = true }), which correctly clones new plugins at their lockfile versions. But then lock.update() runs and rewrites the lockfile for every plugin, including ones already installed at stale versions. The lockfile silently drifts to match local state.

  2. :Lazy restore — calls update({ lockfile = true }). Same issue: plugins are checked out at lockfile versions, then lock.update() immediately overwrites the lockfile. In practice this is mostly a no-op (since restore just moved everything to the right versions), but it shouldn't be rewriting the lockfile at all — the whole point of restore is that the lockfile is the source of truth.

Concrete scenario

Machine A updates plugins, commits lazy-lock.json. Machine B pulls the config. On next startup:

  1. install.missing installs any new plugins at lockfile versions ✓
  2. lock.update() rewrites the lockfile from disk state of all plugins, including ones that were already locally installed at older versions ✗
  3. The lockfile now reflects Machine B's stale local state, not Machine A's intended versions

The user has no window to run :Lazy restore — the lockfile is already overwritten by step 2. Even checking out the old lockfile and restarting Neovim repeats the same cycle (if new plugins exist in the spec, triggering install.missinglock.update()).

The fix

The lockfile option already means "use lockfile versions for checkout." This PR makes it also mean "don't overwrite the lockfile afterward":

  • lockfile=true → lockfile is an input (check out pinned versions, preserve it)
  • lockfile=false/nil → lockfile is an output (use latest, record what we got)

Explicit user commands (:Lazy install, :Lazy update, :Lazy sync) don't pass lockfile=true, so their behavior is unchanged — they still update the lockfile as before.

Testing

Verified both scenarios locally with the patched init.lua:

  1. Missing plugin: Deleted plenary.nvim from disk. Started Neovim → install.missing cloned it at the lockfile-pinned commit. Lockfile was not modified.

  2. Wrong version: Checked out plenary.nvim to an older commit. Started Neovim → install.missing didn't trigger (plugin exists). Ran :Lazy restore → plugin updated to lockfile commit. Lockfile was not modified.

Relates to #1279.

When `lockfile=true` (used by `install.missing` on startup and
`:Lazy restore`), the lockfile is the source of truth and should
not be overwritten. Previously, `lock.update()` was called
unconditionally after install/update, rewriting the entire lockfile
from the current disk state of all plugins — discarding pinned
versions for already-installed plugins.

Skip `lock.update()` when `opts.lockfile` is set, so that:
- startup auto-install (`install.missing`) no longer overwrites
  the lockfile
- `:Lazy restore` no longer overwrites the lockfile
- explicit `:Lazy install` and `:Lazy update` still update it

Fixes folke#1279
@github-actions github-actions Bot added the size/s Small PR (<10 lines changed) label Feb 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s Small PR (<10 lines changed)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant