Skip to content

Gitsigns blame fails after edit, undo, edit #1156

@AndreasNasman

Description

@AndreasNasman

Description

The following error happens after editing a file, undoing the change, and then editing it again:

Error executing Lua callback: ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/async.lua:95: The async coroutine failed: ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsig
ns/async.lua:95: The async coroutine failed: ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/blame.lua:104: Invalid 'replacement string' item: expected String, got nil
                                                                                                                                                                         
stack traceback:                                                                                                                                                         
        [C]: in function 'nvim_buf_set_lines'                                                                                                                            
        ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/blame.lua:104: in function 'render'                                                                            
        ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/blame.lua:293: in function <...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/blame.lua:270>                   
stack traceback:                                                                                                                                                         
        [C]: in function 'error'                                                                                                                                         
        ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/async.lua:95: in function 'step'                                                                               
        ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/async.lua:130: in function 'f'                                                                                 
        ...local/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/cli.lua:96: in function <...local/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/cli.lua:61>                     
stack traceback:                                                                                                                                                         
        [C]: in function 'error'                                                                                                                                         
        ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/async.lua:95: in function 'step'                                                                               
        ...cal/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/async.lua:130: in function 'run'                                                                               
        ...se/.local/share/nvim/lazy/gitsigns.nvim/lua/gitsigns.lua:120: in function <...se/.local/share/nvim/lazy/gitsigns.nvim/lua/gitsigns.lua:119>                   

Neovim version

NVIM v0.11.0-dev-4456+g517ecb85f5-Homebrew Build type: Release LuaJIT 2.1.1732813678

Operating system and version

macOS 14.7.1 (23H222)

Expected behavior

:Gitsigns blame should open without an error after edit-undo-edit on a file.

Actual behavior

The error in the description is thrown:
image

Minimal config

for name, url in pairs{
  gitsigns = 'https://github.com/lewis6991/gitsigns.nvim',
  -- ADD OTHER PLUGINS _NECESSARY_ TO REPRODUCE THE ISSUE
  -- No other plugins.
} do
local install_path = vim.fn.fnamemodify('gitsigns_issue/'..name, ':p')
if vim.fn.isdirectory(install_path) == 0 then
vim.fn.system { 'git', 'clone', '--depth=1', url, install_path }
end
vim.opt.runtimepath:append(install_path)
end

require('gitsigns').setup{
  debug_mode = true, -- You must add this to enable debug messages
  -- ADD GITSIGNS CONFIG THAT IS _NECESSARY_ FOR REPRODUCING THE ISSUE
  -- The default config triggers the error, like `opts = {}` in lazy.nvim.
}

-- ADD INIT.LUA SETTINGS THAT IS _NECESSARY_ FOR REPRODUCING THE ISSUE
-- No settings.

Steps to reproduce

  1. mkdir gitsigns_issue
  2. cd gitsigns_issue
  3. git init
  4. echo -e "foo\nbar" > file
  5. git add file
  6. git commit -m 'initial commit'
  7. nvim --clean -u minimal.lua file
  8. Keep the cursor on line 1 and add a new line with o.
  9. Run :Gitsigns blame and close the blame window.
  10. Press u to undo the change.
  11. Edit the file again, adding a line with o.
  12. Run :Gitsigns blame. This triggers the error.
Screen.Recording.2024-12-13.at.23.32.12.mp4

Gitsigns debug messages

:Gitsigns debug_messages
0.97 D dprintf: Deriving GitSignsAdd from Added
1.04 D derive: Deriving GitSignsChange from Changed
1.07 D derive: Deriving GitSignsDelete from Removed
1.12 D derive: Deriving GitSignsChangedelete from GitSignsChange
1.15 D derive: Deriving GitSignsTopdelete from GitSignsDelete
1.16 D derive: Deriving GitSignsUntracked from GitSignsAdd
1.19 D derive: Deriving GitSignsAddNr from GitSignsAdd
1.21 D derive: Deriving GitSignsChangeNr from GitSignsChange
1.25 D derive: Deriving GitSignsDeleteNr from GitSignsDelete
1.26 D derive: Deriving GitSignsChangedeleteNr from GitSignsChangeNr
1.28 D derive: Deriving GitSignsTopdeleteNr from GitSignsDeleteNr
1.32 D derive: Deriving GitSignsUntrackedNr from GitSignsAddNr
1.35 D derive: Deriving GitSignsAddLn from DiffAdd
1.36 D derive: Deriving GitSignsChangeLn from DiffChange
1.44 D derive: Deriving GitSignsChangedeleteLn from GitSignsChangeLn
1.45 D derive: Deriving GitSignsUntrackedLn from GitSignsAddLn
1.46 D derive: Deriving GitSignsAddCul from GitSignsAdd
1.47 D derive: Deriving GitSignsChangeCul from GitSignsChange
1.49 D derive: Deriving GitSignsDeleteCul from GitSignsDelete
1.50 D derive: Deriving GitSignsChangedeleteCul from GitSignsChangeCul
1.51 D derive: Deriving GitSignsTopdeleteCul from GitSignsDeleteCul
1.54 D derive: Deriving GitSignsUntrackedCul from GitSignsAddCul
1.55 D derive: Deriving GitSignsStagedAdd from GitSignsAdd
1.56 D derive: Deriving GitSignsStagedChange from GitSignsChange
1.58 D derive: Deriving GitSignsStagedDelete from GitSignsDelete
1.60 D derive: Deriving GitSignsStagedChangedelete from GitSignsChangedelete
1.61 D derive: Deriving GitSignsStagedTopdelete from GitSignsTopdelete
1.62 D derive: Deriving GitSignsStagedAddNr from GitSignsAddNr
1.64 D derive: Deriving GitSignsStagedChangeNr from GitSignsChangeNr
1.66 D derive: Deriving GitSignsStagedDeleteNr from GitSignsDeleteNr
1.68 D derive: Deriving GitSignsStagedChangedeleteNr from GitSignsChangedeleteNr
1.69 D derive: Deriving GitSignsStagedTopdeleteNr from GitSignsTopdeleteNr
1.70 D derive: Deriving GitSignsStagedAddLn from GitSignsAddLn
1.73 D derive: Deriving GitSignsStagedChangeLn from GitSignsChangeLn
1.74 D derive: Could not derive GitSignsStagedDeleteLn
1.75 D derive: Deriving GitSignsStagedChangedeleteLn from GitSignsChangedeleteLn
1.76 D derive: Could not derive GitSignsStagedTopdeleteLn
1.77 D derive: Deriving GitSignsStagedAddCul from GitSignsAddCul
1.78 D derive: Deriving GitSignsStagedChangeCul from GitSignsChangeCul
1.79 D derive: Deriving GitSignsStagedDeleteCul from GitSignsDeleteCul
1.80 D derive: Deriving GitSignsStagedChangedeleteCul from GitSignsChangedeleteCul
1.81 D derive: Deriving GitSignsStagedTopdeleteCul from GitSignsTopdeleteCul
1.83 D derive: Deriving GitSignsAddPreview from DiffAdd
1.84 D derive: Deriving GitSignsDeletePreview from DiffDelete
1.55 D derive: Deriving GitSignsStagedAdd from GitSignsAdd                                                                                                               
1.56 D derive: Deriving GitSignsStagedChange from GitSignsChange                                                                                                         
1.58 D derive: Deriving GitSignsStagedDelete from GitSignsDelete                                                                                                         
1.60 D derive: Deriving GitSignsStagedChangedelete from GitSignsChangedelete                                                                                             
1.61 D derive: Deriving GitSignsStagedTopdelete from GitSignsTopdelete                                                                                                   
1.62 D derive: Deriving GitSignsStagedAddNr from GitSignsAddNr                                                                                                           
1.64 D derive: Deriving GitSignsStagedChangeNr from GitSignsChangeNr                                                                                                     
1.66 D derive: Deriving GitSignsStagedDeleteNr from GitSignsDeleteNr                                                                                                     
1.68 D derive: Deriving GitSignsStagedChangedeleteNr from GitSignsChangedeleteNr                                                                                         
1.69 D derive: Deriving GitSignsStagedTopdeleteNr from GitSignsTopdeleteNr                                                                                               
1.70 D derive: Deriving GitSignsStagedAddLn from GitSignsAddLn                                                                                                           
1.73 D derive: Deriving GitSignsStagedChangeLn from GitSignsChangeLn                                                                                                     
1.74 D derive: Could not derive GitSignsStagedDeleteLn                                                                                                                   
1.75 D derive: Deriving GitSignsStagedChangedeleteLn from GitSignsChangedeleteLn                                                                                         
1.76 D derive: Could not derive GitSignsStagedTopdeleteLn                                                                                                                
1.77 D derive: Deriving GitSignsStagedAddCul from GitSignsAddCul                                                                                                         
1.78 D derive: Deriving GitSignsStagedChangeCul from GitSignsChangeCul                                                                                                   
1.79 D derive: Deriving GitSignsStagedDeleteCul from GitSignsDeleteCul                                                                                                   
1.80 D derive: Deriving GitSignsStagedChangedeleteCul from GitSignsChangedeleteCul                                                                                       
1.81 D derive: Deriving GitSignsStagedTopdeleteCul from GitSignsTopdeleteCul                                                                                             
1.83 D derive: Deriving GitSignsAddPreview from DiffAdd                                                                                                                  
1.84 D derive: Deriving GitSignsDeletePreview from DiffDelete                                                                                                            
1.85 D derive: Deriving GitSignsCurrentLineBlame from NonText                                                                                                            
1.86 D derive: Deriving GitSignsAddInline from TermCursor                                                                                                                
1.87 D derive: Deriving GitSignsDeleteInline from TermCursor                                                                                                             
1.88 D derive: Deriving GitSignsChangeInline from TermCursor                                                                                                             
1.90 D derive: Deriving GitSignsAddLnInline from GitSignsAddInline                                                                                                       
1.93 D derive: Deriving GitSignsChangeLnInline from GitSignsChangeInline                                                                                                 
1.94 D derive: Deriving GitSignsDeleteLnInline from GitSignsDeleteInline                                                                                                 
1.97 D derive: Deriving GitSignsDeleteVirtLn from DiffDelete                                                                                                             
1.98 D derive: Deriving GitSignsDeleteVirtLnInLine from GitSignsDeleteLnInline                                                                                           
1.99 D derive: Deriving GitSignsVirtLnum from GitSignsDeleteVirtLn                                                                                                       
14.80 D attach(1): Attaching (trigger=BufReadPost)                                                                                                                       
14.86 D run_job: git --version                                                                                                                                           
20.08 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 rev-parse --show-toplevel --absolute-git-dir --abbrev-ref HEAD                      
24.81 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /Users/nasse/Projects/gitsigns_issue/.git config user.name                
28.83 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /Users/nasse/Projects/gitsigns_issue/.git -c core.quotepath=off ls-files -
-stage --others --exclude-standard --eol /Users/nasse/Projects/gitsigns_issue/file                                                                                       
33.84 D watch_gitdir(1): Watching git dir                                                                                                                                
34.06 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /Users/nasse/Projects/gitsigns_issue/.git show 3bd1f0e29744a1f32b08d5650e6
2e2e62afb177c                                                                                                                                                            
38.76 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /Users/nasse/Projects/gitsigns_issue/.git show HEAD:file                  
5479.10 D cli.run: Running action 'blame' with arguments {}                                                                                                              
5480.38 D run_job: git --no-pager --no-optional-locks --literal-pathspecs -c gc.auto=0 --git-dir /Users/nasse/Projects/gitsigns_issue/.git blame --contents - --increment
al -- /Users/nasse/Projects/gitsigns_issue/file                                                                                                                          
9618.14 D cli.run: Running action 'blame' with arguments {}                                                                                                              
14200.82 D cli.run: Running action 'debug_messages' with arguments {}                                                                                                    
Press ENTER or type command to continue

Gitsigns cache

:Gitsigns dump_cache                                                                                                                                                     
{ {                                                                                                                                                                      
    blame = { "...",                                                                                                                                                     
      length = 2                                                                                                                                                         
    },                                                                                                                                                                   
    bufnr = 1,                                                                                                                                                           
    compare_text = { "...",                                                                                                                                              
      head = "foo",                                                                                                                                                      
      length = 3                                                                                                                                                         
    },                                                                                                                                                                   
    compare_text_head = { "...",                                                                                                                                         
      head = "foo",                                                                                                                                                      
      length = 3                                                                                                                                                         
    },                                                                                                                                                                   
    file = "/Users/nasse/Projects/gitsigns_issue/file",                                                                                                                  
    force_next_update = false,                                                                                                                                           
    git_obj = {                                                                                                                                                          
      encoding = "utf-8",                                                                                                                                                
      file = "/Users/nasse/Projects/gitsigns_issue/file",                                                                                                                
      i_crlf = false,                                                                                                                                                    
      mode_bits = "100644",                                                                                                                                              
      object_name = "3bd1f0e29744a1f32b08d5650e62e2e62afb177c",                                                                                                          
      relpath = "file",                                                                                                                                                  
      repo = {                                                                                                                                                           
        abbrev_head = "main",                                                                                                                                            
        detached = false,                                                                                                                                                
        gitdir = "/Users/nasse/Projects/gitsigns_issue/.git",                                                                                                            
        toplevel = "/Users/nasse/Projects/gitsigns_issue",                                                                                                               
        username = "Andreas Näsman"                                                                                                                                      
      },                                                                                                                                                                 
      w_crlf = false                                                                                                                                                     
    },                                                                                                                                                                   
    gitdir_watcher = <userdata 1>,                                                                                                                                       
    hunks = { "...",                                                                                                                                                     
      head = {                                                                                                                                                           
        added = {                                                                                                                                                        
          count = 1,                                                                                                                                                     
          lines = { "" },                                                                                                                                                
          start = 2                                                                                                                                                      
        },                                                                                                                                                               
        head = "@@ -1 +2,1 @@",                                                                                                                                          
        removed = {                                                                                                                                                      
          count = 0,                                                                                                                                                     
          lines = {},                                                                                                                                                    
          start = 1                                                                                                                                                      
        },                                                                                                                                                               
        type = "add",                                                                                                                                                    
        vend = 2                                                                                                                                                         
      },                                                                                                                                                                 
      length = 1                                                                                                                                                         
    },                                                                                                                                                                   
    hunks_staged = { "...",                                                                                                                                              
      length = 0                                                                                                                                                         
    },                                                                                                                                                                   
    staged_diffs = { "...",                                                                                                                                              
      length = 0                                                                                                                                                         
    }                                                                                                                                                                    
  } }                                                                                                                                                                    
Press ENTER or type command to continue

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