LSP: nil reference in `compute_start_range`
Problem
Error executing lua callback: /usr/local/share/nvim/runtime/lua/vim/lsp/sync.lua:142: attempt to get length of local 'prev_line' (a nil value)
stack traceback:
/usr/local/share/nvim/runtime/lua/vim/lsp/sync.lua:142: in function 'compute_start_range'
/usr/local/share/nvim/runtime/lua/vim/lsp/sync.lua:390: in function 'compute_diff'
...local/share/nvim/runtime/lua/vim/lsp/_changetracking.lua:106: in function 'incremental_changes'
...local/share/nvim/runtime/lua/vim/lsp/_changetracking.lua:311: in function 'send_changes_for_group'
...local/share/nvim/runtime/lua/vim/lsp/_changetracking.lua:348: in function 'send_changes'
/usr/local/share/nvim/runtime/lua/vim/lsp.lua:869: in function </usr/local/share/nvim/runtime/lua/vim/lsp.lua:863>
Related: https://github.com/neovim/neovim/issues/33142
Steps to reproduce using "nvim -u minimal_init.lua"
Don't have exact steps. Try using lsp-driven autocompletion in a buftype=prompt buffer.
Expected behavior
lsp module should never fail in this way. It should check that buffers/windows are valid before trying to operate on them.
Nvim version (nvim -v)
0.12
Language server name/version
any
Operating system/version
macos
Log file
No response
Hi, I am getting a similar error message when using :AvanteEdit on a block of code that begins with file first line (I think). It does not happen with neovim 0.10.4, is reproducible every time with 0.11.0. Thank you.
Error executing vim.schedule lua callback: ...cal/share/nvim/lazy/avante.nvim/lua/avante/selection.lua:164: Vim:Error executing lua callback
: ...unwrapped-0.11.0/share/nvim/runtime/lua/vim/lsp/sync.lua:195: attempt to get length of local 'prev_line' (a nil value)
stack traceback:
...unwrapped-0.11.0/share/nvim/runtime/lua/vim/lsp/sync.lua:195: in function 'compute_end_range'
...unwrapped-0.11.0/share/nvim/runtime/lua/vim/lsp/sync.lua:401: in function 'compute_diff'
....11.0/share/nvim/runtime/lua/vim/lsp/_changetracking.lua:106: in function 'incremental_changes'
....11.0/share/nvim/runtime/lua/vim/lsp/_changetracking.lua:311: in function 'send_changes_for_group'
....11.0/share/nvim/runtime/lua/vim/lsp/_changetracking.lua:348: in function 'send_changes'
...ovim-unwrapped-0.11.0/share/nvim/runtime/lua/vim/lsp.lua:869: in function <...ovim-unwrapped-0.11.0/share/nvim/runtime/lua/vim/ls
p.lua:863>
[C]: in function 'nvim_buf_set_lines'
...cal/share/nvim/lazy/avante.nvim/lua/avante/selection.lua:164: in function ''
vim/_editor.lua: in function <vim/_editor.lua:0>
stack traceback:
[C]: in function 'nvim_buf_set_lines'
...cal/share/nvim/lazy/avante.nvim/lua/avante/selection.lua:164: in function ''
vim/_editor.lua: in function <vim/_editor.lua:0>
@Kamilcuk are you using vim.lsp.config / vim.lsp.enable ? I'm wondering if this correlates with that.
In Neovim 0.11, this error occurs whenever a swap file is present for the active buffer. Deleting the swap file fixes the error.
are you using vim.lsp.config / vim.lsp.enable ?
yes
@justinmk Hey, I've observed the issue described by @Kamilcuk as well (currently on nightly), calling:
:lua vim.api.nvim_buf_set_lines(0, 0, 0, false, {})
on empty file with single line explodes on the assert
https://github.com/neovim/neovim/blob/a0d94ac4692a046e88850d512112754c4b8d7013/runtime/lua/vim/lsp/sync.lua#L192-L195
Unless you have steps to repro with nvim --clean, don't bother with "me too" comments.
Literally the comment above this one says to stop posting "me too" comments. Read the room, people.
This type of issues will come more and more as we use more agentic ai , the situation of having an external process modifying buffers that you have opened in nvim.
I've worked with claude for a bit to come up with a "fix" obvs this needs testing and what not
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
index 36a94d5fba..9783b7856f 100644
--- a/runtime/lua/vim/lsp/sync.lua
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -133,8 +133,14 @@ local function compute_start_range(
return { line_idx = firstline, byte_idx = 1, char_idx = 1 }
end
- local prev_line = assert(prev_lines[firstline])
- local curr_line = assert(curr_lines[firstline])
+ -- Bounds check: ensure prev_lines and curr_lines have the required indices
+ if not prev_lines or not prev_lines[firstline] or not curr_lines or not curr_lines[firstline] then
+ -- If we can't get the lines, return a safe default
+ return { line_idx = firstline, byte_idx = 1, char_idx = 1 }
+ end
+
+ local prev_line = prev_lines[firstline]
+ local curr_line = curr_lines[firstline]
-- Iterate across previous and current line containing first change
-- to find the first different byte.
@@ -192,12 +198,17 @@ local function compute_end_range(
-- A special case for the following `firstline == new_lastline` case where lines are deleted.
-- Even if the buffer has become empty, nvim behaves as if it has an empty line with eol.
if #curr_lines == 1 and curr_lines[1] == '' then
- local prev_line = assert(prev_lines[lastline - 1])
- return {
- line_idx = lastline - 1,
- byte_idx = #prev_line + 1,
- char_idx = str_utfindex(prev_line, position_encoding) + 1,
- }, { line_idx = 1, byte_idx = 1, char_idx = 1 }
+ if prev_lines and prev_lines[lastline - 1] then
+ local prev_line = prev_lines[lastline - 1]
+ return {
+ line_idx = lastline - 1,
+ byte_idx = #prev_line + 1,
+ char_idx = str_utfindex(prev_line, position_encoding) + 1,
+ }, { line_idx = 1, byte_idx = 1, char_idx = 1 }
+ else
+ -- Fallback if prev_line doesn't exist
+ return { line_idx = lastline - 1, byte_idx = 1, char_idx = 1 }, { line_idx = 1, byte_idx = 1, char_idx = 1 }
+ end
end
-- If firstline == new_lastline, the first change occurred on a line that was deleted.
-- In this case, the last_byte...
@@ -222,8 +233,13 @@ local function compute_end_range(
local prev_line_idx = lastline - 1
local curr_line_idx = new_lastline - 1
- local prev_line = assert(prev_lines[lastline - 1])
- local curr_line = assert(curr_lines[new_lastline - 1])
+ -- Bounds check for last lines
+ if not prev_lines or not prev_lines[lastline - 1] or not curr_lines or not curr_lines[new_lastline - 1] then
+ return { line_idx = lastline - 1, byte_idx = 1, char_idx = 1 }, { line_idx = new_lastline - 1, byte_idx = 1, char_idx = 1 }
+ end
+
+ local prev_line = prev_lines[lastline - 1]
+ local curr_line = curr_lines[new_lastline - 1]
local prev_line_length = #prev_line
local curr_line_length = #curr_line
48 hours in , so far so good
This type of issues will come more and more as we use more agentic ai
Yes, but regardless of AI, we should handle this better. Did you send a PR, ideally with a test? Thanks!
Hi @bechampion,
Is it possible to create a PR for this?
Thanks a lot