hrsh7th / nvim-cmp

A completion plugin for neovim coded in Lua.
MIT License
7.45k stars 370 forks source link

Error of : start_col out of bounds. Extra characters at the end of completions. #1560

Open MostHated opened 1 year ago

MostHated commented 1 year ago

FAQ

Announcement

Minimal reproducible full config

Unfortunately, I cannot reliably reproduce this. It happens randomly, and I have to close and reopen nvim.

Description

I am having the same issue as described in issue https://github.com/hrsh7th/nvim-cmp/issues/1097 but that one said to open a new issue.

Sometimes I will start to notice that completions will have extra characters at the end. Today was the first time that I recall seeing an actual error, which can be seen below.

Example: I start to type something, and at the end of the completion, it should end with "); but it ends with ");");. Yesterday, I noticed that it was doing this, but with a newline as well.

Ex. Expected this:

let whatever = whatever("whatever");

Got this:

let whatever = whatever("whatever");
);

Below are my version numbers, as well as the actual error message that appeared this time, which prompted my searching and coming across the issue mentioned above.

Versions

NVIM v0.9.0-dev-554+g6f25623e7
Build type: RelWithDebInfo
LuaJIT 2.1.0-beta3

● nvim-cmp 0.7ms  lsp-zero.nvim
    dir    /home/mosthated/.local/share/nvim/lazy/nvim-cmp
    url    https://github.com/hrsh7th/nvim-cmp
    branch main
    commit 1cad30f
    readme README.md
    help   |nvim-cmp|
Error  04:58:19 PM msg_show.lua_error E5108: Error executing lua ...sthated/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:383: start_col out of bounds
stack traceback:
    [C]: in function 'nvim_buf_set_text'
    ...sthated/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:383: in function <...sthated/.local/share/nvim/lazy/nvim-cmp/lua/cmp/core.lua:371>
    ...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/utils/feedkeys.lua:47: in function <...ocal/share/nvim/lazy/nvim-cmp/lua/cmp/utils/feedkeys.lua:45>

Steps to reproduce

Unfortunately, it is seemingly pretty random. I am not sure how to forcefully reproduce it. So far, I have only noticed it in Rust, but at the same time, I have only really been writing Rust the last few weeks.

Expected behavior

No error or extra characters in completions

Actual behavior

Error and extra characters in completions

Additional context

No response

hrsh7th commented 1 year ago

I can't fix without repro steps...

Is this problem caused if you type multibyte character?

MostHated commented 1 year ago

I understand that. I am trying to contribute what I can by reporting an issue. I don't expect you to be able to fix it with that I have provided alone, but I also didn't want to simply ignore the fact that an error occurred.

I am honestly not 100% sure of what characters are multibyte. I know a good number of non-english characters are, but are typical symbols used in programming multibyte? Ex: &, or !, etc? I don't/have not used any out of the ordinary characters that are not on a typical english keyboard.

I will try and pay attention the next time it occurs and will see try and come back with the exact characters I tried to type, and what the completion was.

ActionScripted commented 1 year ago

I'm not sure if this helps at all but for me it seems to happen when using Copilot (nvim-cmp, copilot-cmp, copilot.lua) and tab completion. When I use arrow keys things don't seem to break but if I use tab to cycle between options and then hit return I get Invalid 'start_col': out of range

But only sometimes. When I save/close the file and reopen and try the same completion oftentimes it works. I saw elsewhere something about async maybe being a cause, maybe that's what is going on.

Again sorry for not being more helpful but here's my lazy.vim config for nvim-cmp:

--[[
-- Auto-complete
--]]
return {
  {
    "hrsh7th/nvim-cmp",
    version = false, -- last release is way too old
    --event = "InsertEnter",
    dependencies = {
      "hrsh7th/cmp-nvim-lsp",
      "hrsh7th/cmp-buffer",
      "hrsh7th/cmp-path",
      --"hrsh7th/cmp-cmdline",
      "saadparwaiz1/cmp_luasnip",
      "L3MON4D3/LuaSnip",
      {
        "zbirenbaum/copilot-cmp",
        dependencies = {
          {
            "zbirenbaum/copilot.lua",
            cmd = "Copilot",
            build = ":Copilot auth",
            opts = {
              suggestion = { enabled = false },
              panel = { enabled = false },
            },
          },
        },
        opts = {},
        config = function(_, opts)
          local copilot_cmp = require("copilot_cmp")
          copilot_cmp.setup(opts)
          -- attach cmp source whenever copilot attaches
          -- fixes lazy-loading issues with the copilot cmp source
          require("lazyvim.util").on_attach(function(client)
            if client.name == "copilot" then
              copilot_cmp._on_insert_enter()
            end
          end)
        end,
      },
    },
    opts = function()
      local cmp = require("cmp")
      return {
        completion = {
          completeopt = "menu,menuone,noinsert",
        },
        snippet = {
          expand = function(args)
            require("luasnip").lsp_expand(args.body)
          end,
        },
        mapping = cmp.mapping.preset.insert({
          ['<Tab>'] = function(fallback)
            if cmp.visible() then cmp.select_next_item() else fallback() end
          end,
          ['<S-Tab>'] = function(fallback)
            if cmp.visible() then cmp.select_prev_item() else fallback() end
          end,
          ["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
          ["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
          ["<C-b>"] = cmp.mapping.scroll_docs(-4),
          ["<C-f>"] = cmp.mapping.scroll_docs(4),
          ["<C-Space>"] = cmp.mapping.complete(),
          ["<C-e>"] = cmp.mapping.abort(),
          -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
          ["<CR>"] = cmp.mapping.confirm({ 
            behavior = cmp.ConfirmBehavior.Replace,
            select = false
          }),
          -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
          ["<S-CR>"] = cmp.mapping.confirm({
            behavior = cmp.ConfirmBehavior.Replace,
            select = true,
          }),
        }),
        sources = cmp.config.sources({
          { name = "buffer" },
          { name = "copilot" },
          { name = "pylsp" },
          { name = "luasnip" },
          { name = "nvim_lsp" },
          { name = "path" },
          --{ name = "cmdline" },
        }),
        formatting = {
          format = function(_, item)
            local icons = require("lazyvim.config").icons.kinds
            if icons[item.kind] then
              item.kind = icons[item.kind] .. item.kind
            end
            return item
          end,
        },
        experimental = {
          ghost_text = {
            hl_group = "LspCodeLens",
          },
        },
      }
    end,
  },
}

It's mostly stolen from LazyVim with a few tweaks to toss it all into a single table because I'm testing stuff for a new setup and that's easier.

Trying to trigger it, everything in this file worked until the last comment # run main from Copilot. That's when the error was thrown:

Screenshot 2023-05-09 at 1 13 56 PM
MostHated commented 1 year ago

I just had this occur, not the error, but the extra characters:

Below is where it occurred:

#[warn(dead_code)])]  // <-- End Result 
pub enum MatcherKind {
  Include(Gitignore),
  Exclude(Gitignore),
}

With the code above, I had typed out this much:

#[warn(

The completion was supposed to be:

dead_code)]

but ended up being:

dead_code)])]

It was actually a copilot completion, similar to above, but I don't use tab for the completion. I use <C-CR> to insert it.

I am not sure if the initial error is related to this, or this is two separate issues that happened to have occurred at the same time.

arpanetus commented 1 year ago

I'm experiencing the same issue right now.

wuminzhe commented 11 months ago

I just had this occur, not the error, but the extra characters:

Below is where it occurred:

#[warn(dead_code)])]  // <-- End Result 
pub enum MatcherKind {
  Include(Gitignore),
  Exclude(Gitignore),
}

With the code above, I had typed out this much:

#[warn(

The completion was supposed to be:

dead_code)]

but ended up being:

dead_code)])]

It was actually a copilot completion, similar to above, but I don't use tab for the completion. I use <C-CR> to insert it.

I am not sure if the initial error is related to this, or this is two separate issues that happened to have occurred at the same time.

same issue

sunyiynus commented 9 months ago

Same Issue in my config

m-wynn commented 9 months ago

I was encountering this and similar errors. I eventually went through and disabled all my other config and plugins, and eventually found https://github.com/hashivim/vim-terraform was causing the majority of my issues with terraform code, at least.

I chose to disable it rather than dig into it to find out what exactly was causing the issue. But it may be worth searching for similar type plugins or settings in your config.

kapral18 commented 6 months ago

CleanShot 2023-12-23 at 21 00 01

my lazyvim starter config: https://github.com/kapral18/config.nvim/blob/a75e0eb57f5748823d9143e3f4ce0b8c2c1b7222/lua/plugins/coding.lua

minhanghuang commented 6 months ago

image

experiencing the same issue right now

8veStory commented 5 months ago

I've had the same issue on MacOS Sonoma using LazyVim.

It only happens for me when I hit <CR> to confirm a copilot.lua/copilot-cmp completion, which seems to be common amongst previous reports. The error is about an 'Invalid start_col' and requires a restart for nvim-cmp to work again.

Doesn't happen all the time though. Possibly async issue? Or perhaps the completion had some funky characters?

I'm using the stock LazyVim Copilot extra detailed here: https://www.lazyvim.org/extras/coding/copilot.

If I run across the error again reliably I'll try update with examples.

kapral18 commented 5 months ago

I noticed that it happens with copilot as well for example when completion menu open and before hitting the completion item you move your cursor in any direction.

Rigidity commented 5 months ago

I'm having the same problem. Also using Copilot + CMP:

image

xiopt commented 5 months ago

Same problem here. copilot-cmp on mac Sonoma with lazyvim.

8veStory commented 5 months ago

So far I've only seen comments/images that mention/show macOS; if this is the case, perhaps it's an OS specific issue?

Rigidity commented 5 months ago

So far I've only seen comments/images that mention/show macOS; if this is the case, perhaps it's an OS specific issue?

I'm on Ubuntu

MostHated commented 5 months ago

I am on Pop_OS (Ubuntu)

akthe-at commented 5 months ago

Same Here, on Windows, Not WSL...Using Nvim 9.5 in Windows Terminal/Git Bash.

viktorholk commented 5 months ago

I'm having the same issue.

On Mac M1

NukaCody commented 4 months ago

As a data point as I can't seem to reproduce consistently but:

This seems to occur randomly based on what copilot returns (using copilot.lua and not github/copilot.vim). Something about copilot generation and nvim-cmp don't get along. It's intermediary because there are times I can accept a change and other times the error is thrown. Oddly enough I'm also writing rust as the original author and other's pointed out in this thread.

pixelprogrammer commented 4 months ago

So far I've only seen comments/images that mention/show macOS; if this is the case, perhaps it's an OS specific issue?

Just confirming that this is not an OS specific issue. I am on Fedora and have had this issue both on Gnome and Sway.

I also don't believe this is language specific either and is happening on Typescript, Go and maybe some Rust projects (haven't tested that one in a bit)

I am unable to get a consistent error but it does appear to be happening a lot. Using the LazyVim setup and this happens when I try to autocomplete a Github Copilot suggestion sometimes. Usually the first few times work well but then it starts to error out after that.

JosefLitos commented 3 months ago

I have the same issue in markdown with cmp-path not updating when quickly writing something with a slash and then going to new line and pressing tab to increase my indent. It keeps showing the same completion on the new line until I've written something on it and it often shows this error in this sequence of actions. The main issue seems to be the menu not updating when changing to a different line.

pixelprogrammer commented 3 months ago

I noticed that it happens with copilot as well for example when completion menu open and before hitting the completion item you move your cursor in any direction.

I think this is the main issue. I have a tendency to hit return twice to give some space. So the cursor ends up one line below and when I do the copilot autocomplete, it errors. This has been consistent on many different languages and can now confirm it happens in Go, Rust, Typescript, PHP, etc.

hrsh7th commented 3 months ago

If the same issue occurs with cmp-path, it may be a core issue.

I don't use copilot, but I've never encountered this problem.

pixelprogrammer commented 3 months ago

If the same issue occurs with cmp-path, it may be a core issue.

I don't use copilot, but I've never encountered this problem.

I have only had this issue with Copilot. Before adding it to Neovim I never had this issue before. So its quite possible this issue stems from there instead. However, should there be a breaking error happening when the cursor position is incorrect? Should it just ignore the action and then display a warning message instead?

This would be for this case here: https://github.com/hrsh7th/nvim-cmp/issues/1560#issuecomment-1868361303

Ddystopia commented 3 months ago

Hello, I do use copilot and encounter this error quite often.

JosefLitos commented 3 months ago

I just managed to reproduce this behaviour intentionally: obrazek

This will change the cursor position without updating the completion menu (probably the root cause):

vim.keymap.set('i', '<Enter>', '\r- ', { buffer = true })

If the space isn't there, the completion menu updates. Just the \r causes the menu to disappear, same without -.

I think it may have something to do with the space being part of the completion source allowed characters?

  1. use cmp-path and provided function/mapping in a file
  2. start editing, write foo /, the completion should trigger or trigger it manually
  3. <CR> (activates the mapping) - the old completion should stay up
  4. using <Left>, navigate to the previous line and <BS> the ' '
  5. now with <Right> navigate back to the end of the next line
  6. complete the completion (<Tab> or whatever your binding is)

during all of 3.+, the completion menu should stay open showing the same completion, by deleting the space, we change the end of the line to before the original position, but the completion doesn't get updated, so tries to complete to an invalid position

The key is that the completion must stay active on its own - manually requesting it (except 2.) will update the menu, same as deleting anything but the ' '. Also it mustn't get updated during the cursor movement, so there must be no new completion items populating the menu.

modk commented 3 months ago

This might be a multi-faceted problem but for me it mainly occurs when entering insert mode (e.g. by pressing 'O' to insert a line above the current one). It looks like in such a case completion works on an outdated buffer (i.e. the one before switching to insert mode) causing the column information to be out of sync. If I switch back to normal mode and re-enter insert mode manually completion works just fine. For the time being the follow hack that does this automatically works for me:

diff --git a/lua/cmp/core.lua b/lua/cmp/core.lua
index b34c360..2267543 100644
--- a/lua/cmp/core.lua
+++ b/lua/cmp/core.lua
@@ -370,6 +370,10 @@ core.confirm = function(self, e, option, callback)
   self.view:close()

   feedkeys.call(keymap.indentkeys(), 'n')
+  -- Exit and re-enter insert mode just in case.  This ensures that the buffer
+  -- is not out of date.
+  local keys = vim.api.nvim_replace_termcodes('<C-c>i', false, false, true)
+  vim.api.nvim_feedkeys(keys, 'n', {})
   feedkeys.call('', 'n', function()
     -- Emulate `<C-y>` behavior to save `.` register.
     local ctx = context.new()
@@ -391,7 +395,7 @@ core.confirm = function(self, e, option, callback)
       vim.cmd([[silent! undojoin]])
       -- This logic must be used nvim_buf_set_text.
       -- If not used, the snippet engine's placeholder wil be broken.
-      vim.api.nvim_buf_set_text(0, e.context.cursor.row - 1, e:get_offset() - 1, ctx.cursor.row - 1, ctx.cursor.col - 1, {
+      vim.api.nvim_buf_set_text(0, e.context.cursor.row - 1, e:get_offset() - 1, ctx.cursor.row - 1, ctx.cursor.col, {
         e.context.cursor_before_line:sub(e:get_offset()),
       })
       vim.api.nvim_win_set_cursor(0, { e.context.cursor.row, e.context.cursor.col - 1 })

That's not a proper solution but I don't know enough about nvim's API or nvim-cmp to come up with something better.

norpadon commented 1 week ago

I have the same issue with copilot when using as a binding.