jesseduffield/lazygit · error
Could not find deleted file or new file for file rename
Error message
Could not find deleted file or new file for file rename
What it means
After refetching the status with --no-renames, BeforeAndAfterFileForRename must find entries matching file.PreviousPath (the deleted side) and file.Path (the added side). If either is missing from the no-renames listing, the rename cannot be split and the error fires. It indicates the file model and the actual working-tree/HEAD status disagree.
Source
Thrown at pkg/commands/git_commands/working_tree.go:111
// all files, passing the --no-renames flag and then recursively call the function
// again for the before file and after file.
filesWithoutRenames := self.fileLoader.GetStatusFiles(GetStatusFileOptions{NoRenames: true})
var beforeFile *models.File
var afterFile *models.File
for _, f := range filesWithoutRenames {
if f.Path == file.PreviousPath {
beforeFile = f
}
if f.Path == file.Path {
afterFile = f
}
}
if beforeFile == nil || afterFile == nil {
return nil, nil, errors.New("Could not find deleted file or new file for file rename")
}
if beforeFile.IsRename() || afterFile.IsRename() {
// probably won't happen but we want to ensure we don't get an infinite loop
return nil, nil, errors.New("Nested rename found")
}
return beforeFile, afterFile, nil
}
// DiscardAllFileChanges directly
func (self *WorkingTreeCommands) DiscardAllFileChanges(file *models.File) error {
if file.IsRename() {
beforeFile, afterFile, err := self.BeforeAndAfterFileForRename(file)
if err != nil {
return err
}
View on GitHub (pinned to c477a2959b)
Solutions
- Refresh the files panel / rerun the action so the model matches the worktree
- Ensure no concurrent process is mutating the index while lazygit acts
- If persistent, run `git status --no-renames` manually and compare against what lazygit shows to spot path encoding oddities
Defensive patterns
Strategy: retry
Validate before calling
freshFiles := fileLoader.GetStatusFiles(GetStatusFileOptions{NoRenames: true})
haveBefore, haveAfter := false, false
for _, f := range freshFiles {
haveBefore = haveBefore || f.Path == file.PreviousPath
haveAfter = haveAfter || f.Path == file.Path
}
if !haveBefore || !haveAfter {
return nil, nil, errors.New("rename halves not visible in current status; refresh")
} Try / catch
On this error, re-fetch file status and retry the discard/split once — the usual cause is a stale model catching up. A second failure means genuine worktree divergence; stop and surface the state to the user.
Prevention
- Avoid mutating the index from outside lazygit while using it
- Trigger a files refresh after external commands (formatters, editors)
- Don't hold *models.File pointers across user pauses
When it happens
Trigger: Stale file model: the rename was already staged/discarded/committed between refresh and action; paths needing quoting where the listing round-trips differently; submodules or symlinks that never appear as separate delete+add pairs under --no-renames.
Common situations: Acting on a rename in the files panel right as a background refresh or another process (editor, formatter, second git invocation) changed the worktree.
Related errors
- Expected renamed file
- Nested rename found
- You have no tracked/staged files to stash
- Git version must be at least %s. Please upgrade your git ver
- Lazygit does not support bare repos.
AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15).
Data as JSON: /api/errors/df3130c30ceae8a8.
Report an issue: GitHub.