plandex-ai/plandex · warning
error dropping git stash: %v
Error message
error dropping git stash: %v
What it means
After resolving stash-pop conflicts with `git checkout --ours`, GitStashPop drops the stash with `git stash drop`. This error wraps a failure of that drop command, including git's output. The conflicted files were reset, but the stash entry remains, so the working tree is resolved but the stash is not cleaned up.
Source
Thrown at app/cli/lib/git.go:159
if !forceOverwrite {
return fmt.Errorf("conflict popping git stash: %s", string(res))
}
// Parse the output to find which files have conflicts
conflictFiles := parseConflictFiles(string(res))
log.Println("Conflicting files:", conflictFiles)
for _, file := range conflictFiles {
// Reset each conflicting file individually
checkoutRes, err := exec.Command("git", "checkout", "--ours", file).CombinedOutput()
if err != nil {
return fmt.Errorf("error resetting file %s: %v", file, string(checkoutRes))
}
}
dropRes, err := exec.Command("git", "stash", "drop").CombinedOutput()
if err != nil {
return fmt.Errorf("error dropping git stash: %v", string(dropRes))
}
return nil
} else {
log.Println("No conflicts detected")
return fmt.Errorf("error popping git stash: %v", string(res))
}
}
return nil
}
func GitClearUncommittedChanges() error {
gitMutex.Lock()
defer gitMutex.Unlock()
// Reset staged changes
res, err := exec.Command("git", "reset", "--hard").CombinedOutput()View on GitHub (pinned to e2d772072e)
Solutions
- Check `git stash list`; if the message is 'No stash entries found', the stash is already gone and this is harmless — proceed.
- Remove stale .git/index.lock if a git process is stuck.
- If the stash ref is corrupted, delete it: `git stash clear` or remove .git/refs/stash.
- Retry the drop manually: `git stash drop` and verify output.
- Ensure only one process manipulates the stash stack at a time.
Example fix
// before: treating drop failure as fatal even when stash is empty
if err := lib.GitStashPop(true); err != nil { return err }
// after: tolerate missing stash
if err := lib.GitStashPop(true); err != nil && strings.Contains(err.Error(), "No stash entries") {
err = nil // stash already gone
} Defensive patterns
Strategy: try-catch
Validate before calling
// Go: confirm a stash exists before pop/drop
out, err := exec.Command("git", "stash", "list").Output()
hasStash := err == nil && strings.TrimSpace(string(out)) != "" Type guard
func isStashDropError(err error) bool {
return err != nil && strings.Contains(err.Error(), "error dropping git stash")
} Try / catch
if err := lib.GitStashPop(true); err != nil {
if isStashDropError(err) && strings.Contains(err.Error(), "No stash entries") {
err = nil // stash already consumed; treat as success
}
} Prevention
- Check `git stash list` before pop/drop flows so a missing stash is expected, not an error.
- Never run multiple processes that mutate the stash stack concurrently.
- Treat 'No stash entries found' as an idempotent success in cleanup paths.
- Monitor for corrupted .git/refs/stash in long-lived checkouts.
When it happens
Trigger: GitStashPop(true) successfully reset all conflict files, then `git stash drop` failed — usually because there is no stash entry left (it was already popped/dropped or never created), the reflog/stash ref is corrupted, or the index is locked.
Common situations: Another process or a prior crashed run already consumed the stash (`No stash entries found`); concurrent GitStashPop calls racing on the same stash stack despite the mutex; corrupted .git/refs/stash.
Related errors
- error creating git stash: %v, output: %s
- conflict popping git stash: %s
- error resetting file %s: %v
- error popping git stash: %v
- error getting git root: %s
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/6c3561a0e71835ee.
Report an issue: GitHub.