Skip to content

bug(picker): jumping to a terminal buffer fails with "Invalid cursor line: out of range" #2939

Description

@truls27a

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.4

Operating system/version

macOS 26.5.2

Describe the bug

Confirming a terminal buffer in the buffers picker sometimes fails with:

vim.schedule callback: .../snacks/picker/actions.lua:149: Invalid cursor line: out of range
stack traceback:
        [C]: in function 'nvim_win_set_cursor'
        .../snacks/picker/actions.lua:149: in function 'jump'
        .../snacks/picker/actions.lua:42: in function <.../snacks/picker/actions.lua:41>

A terminal buffer has one line per row of the window showing it, and Neovim resizes the pty to whatever window displays it. M.file previews a loaded buffer by putting the real buffer in the preview window (picker/preview.lua:110), which shrinks a terminal buffer to the preview's height. With the default layout and lines=60 that is 58 lines down to 46.

The buffers source snapshots pos before that happens (picker/source/buffers.lua:41), and for a terminal you just used it is the last line. M.jump then runs :buffer and sets the cursor on the next line, before the pty has resized back, so it asks for line 58 of a 46-line buffer.

The jump itself succeeds, only the cursor restore is skipped, so the error is cosmetic.

Steps To Reproduce

  1. :terminal, run something short like git status
  2. leave the cursor on the last line and switch to another buffer
  3. Snacks.picker.buffers(), select the terminal, press <cr>

Expected Behavior

Jumping to a buffer with fewer lines than when the picker was opened should place the cursor on the last line instead of raising.

Repro

Reproduces without the picker, using a float of the preview's height:

vim.o.lines = 40
vim.cmd("terminal")
local term = vim.api.nvim_get_current_buf()
vim.fn.chansend(vim.bo[term].channel, "clear; git status --short\n")
vim.wait(1500)
vim.cmd("redraw")
vim.cmd("normal! G")
local pos = vim.api.nvim_win_get_cursor(0)[1] -- 38, the window height
vim.cmd("enew")

-- what the preview does
local float = vim.api.nvim_open_win(term, false, {
  relative = "editor", row = 2, col = 2, width = 60, height = 15, style = "minimal",
})
vim.wait(1500)
vim.cmd("redraw")
vim.api.nvim_win_close(float, true)

vim.cmd("buffer " .. term)
print(vim.api.nvim_buf_line_count(term)) -- 15, not 38
vim.api.nvim_win_set_cursor(0, { pos, 0 }) -- Invalid cursor line: out of range

Proposed Fix

Clamp the line in M.jump:

   if pos and pos[1] > 0 then
-    vim.api.nvim_win_set_cursor(win, { pos[1], pos[2] })
+    local last_line = vim.api.nvim_buf_line_count(vim.api.nvim_win_get_buf(win))
+    vim.api.nvim_win_set_cursor(win, { math.min(pos[1], last_line), pos[2] })
     vim.cmd("norm! zzzv")

The column needs no guard, nvim_win_set_cursor already clamps it. Happy to open a PR.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions