Skip to content

bug(image): converted preview cache stays stale when a local image is replaced #2949

Description

@euri10

Did you check docs and existing issues?

  • I have read all the snacks.nvim docs
  • I have updated the plugin to the latest version before submitting this issue
  • I have searched the existing issues of snacks.nvim
  • I have searched the existing issues of plugins related to this issue

Neovim version (nvim -v)

NVIM v0.12.5 Build type: Release LuaJIT 2.1.1774638290

Operating system/version

debian trixie

Describe the bug

Description

When a local non-PNG image is modified or replaced while keeping the same path, Snacks continues displaying the previously converted image from its disk cache.

This affects image previews in pickers/Explorer and persists after restarting Neovim.

The source file is correct on disk. Removing its converted files from stdpath("cache") .. "/snacks/image" fixes the preview.

Possibly related to #1394, but Snacks.image.image.clear() only clears the in-memory image table. It does not invalidate converted files on disk.

Cause found during investigation

The conversion cache prefix is based only on the normalized source path and page:

self.prefix =
  vim.fn.sha256(self.opts.src .. self.page):sub(1, 8)
  .. "-"
  .. base:gsub("[^%w%.]+", "-")

A conversion step is then considered complete whenever its target exists:

done = uv.fs_stat(file) ~= nil

Neither the source modification time nor its contents participate in cache validation. Consequently, replacing a file at the same path reuses the previous conversion.

This behavior is also present on current main:

https://github.com/folke/snacks.nvim/blob/main/lua/snacks/image/convert.lua

For local files, perhaps the cached derivative could be invalidated whenever the source mtime is newer than the cached file.

Environment

  • Neovim: NVIM v0.12.5
  • Snacks commit: 882c996cf28183f4d63640de0b4c02ec886d01f2
  • OS: Linux 7.0.13+deb13-amd64, x86_64
  • Terminal: Ghostty 1.3.2-main-+76e568b47

Steps To Reproduce

Steps to reproduce

Minimal repro.lua:

vim.pack.add({ "https://github.com/folke/snacks.nvim" })

require("snacks").setup({
  picker = { enabled = true },
  image = { enabled = true },
})

Create the first version:

rm -rf /tmp/snacks-image-repro /tmp/snacks-image-cache
mkdir -p /tmp/snacks-image-repro

magick -size 800x400 xc:red \
  /tmp/snacks-image-repro/image.webp

XDG_CACHE_HOME=/tmp/snacks-image-cache nvim -u repro.lua

In Neovim, open the picker and preview image.webp:

:lua Snacks.picker.files({ cwd = "/tmp/snacks-image-repro" })

The preview is red. Exit Neovim.

Now replace the image without changing its path and create an identical file under a new name:

magick -size 800x400 xc:blue \
  /tmp/snacks-image-repro/image.webp

cp /tmp/snacks-image-repro/image.webp \
   /tmp/snacks-image-repro/expected.webp

sha256sum /tmp/snacks-image-repro/*.webp

The two WebP files have identical contents.

Start Neovim again with the same cache directory:

XDG_CACHE_HOME=/tmp/snacks-image-cache nvim -u repro.lua

Open the same picker:

:lua Snacks.picker.files({ cwd = "/tmp/snacks-image-repro" })
  1. Preview expected.webp: it is blue.
  2. Preview image.webp: it is still red.

The stale preview survives a complete Neovim restart.

Expected Behavior

Expected behavior

image.webp should be reconverted and displayed in blue because its source file changed after the cached conversion was created.

Actual behavior

Snacks displays the old red conversion indefinitely because the cached PNG already exists.

Repro

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions