{"record":{"id":"1f33d7b084b9a369","repo":"plandex-ai/plandex","slug":"error-popping-git-stash-v","errorCode":null,"errorMessage":"error popping git stash: %v","messagePattern":"error popping git stash: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/git.go","lineNumber":165,"sourceCode":"\n\t\t\tlog.Println(\"Conflicting files:\", conflictFiles)\n\n\t\t\tfor _, file := range conflictFiles {\n\t\t\t\t// Reset each conflicting file individually\n\t\t\t\tcheckoutRes, err := exec.Command(\"git\", \"checkout\", \"--ours\", file).CombinedOutput()\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"error resetting file %s: %v\", file, string(checkoutRes))\n\t\t\t\t}\n\t\t\t}\n\t\t\tdropRes, err := exec.Command(\"git\", \"stash\", \"drop\").CombinedOutput()\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error dropping git stash: %v\", string(dropRes))\n\t\t\t}\n\t\t\treturn nil\n\t\t} else {\n\t\t\tlog.Println(\"No conflicts detected\")\n\n\t\t\treturn fmt.Errorf(\"error popping git stash: %v\", string(res))\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc GitClearUncommittedChanges() error {\n\tgitMutex.Lock()\n\tdefer gitMutex.Unlock()\n\n\t// Reset staged changes\n\tres, err := exec.Command(\"git\", \"reset\", \"--hard\").CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error resetting staged changes | err: %v, output: %s\", err, string(res))\n\t}\n\n\t// Clean untracked files\n\tres, err = exec.Command(\"git\", \"clean\", \"-d\", \"-f\").CombinedOutput()","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/git.go#L147-L183","documentation":"When `git stash pop` fails but its output does NOT contain the conflict marker 'overwritten by merge', GitStashPop cannot classify the failure and returns this generic error carrying git's combined output. It signals an unexpected stash-pop failure outside the known conflict path.","triggerScenarios":"Calling GitStashPop when there is no stash to pop ('No stash entries found'), when pop fails for merge reasons producing different wording than the 2.39.3 marker (git version drift), when the working tree has untracked files that would be clobbered ('already exists, no checkout'), or when the index is locked.","commonSituations":"GitStashCreate never ran or its stash was already consumed; newer/older git versions phrase overwrite warnings differently than PopStashConflictMsg; untracked file collisions on pop; running in a repo with an in-progress rebase/merge.","solutions":["Read the output embedded in the error — it is the raw git stash pop stderr/stdout.","If it says 'No stash entries found', either skip popping or guard the flow with GitStashCreate before pop.","If untracked-file collision ('already exists'), delete/rename the offending untracked files and pop again.","If output shows an overwrite conflict phrased differently, update PopStashConflictMsg/parseConflictFiles for your git version or resolve manually (`git checkout --ours` + `git stash drop`).","Abort in-progress rebase/merge states before popping."],"exampleFix":"// before: pop assumed a stash exists\nlib.GitStashPop(false)\n// after: ensure a stash exists first\nif stashed, _ := lib.CheckUncommittedChanges(); stashed {\n    lib.GitStashCreate(\"pre-update\")\n    lib.GitStashPop(false)\n}","handlingStrategy":"validation","validationCode":"// Go: only pop if a stash actually exists\nout, err := exec.Command(\"git\", \"stash\", \"list\").Output()\nif err == nil && strings.TrimSpace(string(out)) != \"\" {\n    lib.GitStashPop(false)\n}","typeGuard":"func isStashPopError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"error popping git stash:\")\n}","tryCatchPattern":"if err := lib.GitStashPop(false); err != nil {\n    if isStashPopError(err) {\n        out := extractAfter(err.Error(), \"output: \")\n        if strings.Contains(out, \"No stash entries found\") {\n            // expected when nothing was stashed — proceed\n        } else if strings.Contains(out, \"already exists\") {\n            // untracked-file collision: remove/rename file and retry\n        } else {\n            // unknown failure: log full git output for diagnosis\n        }\n    }\n}","preventionTips":["Pair every GitStashCreate with exactly one GitStashPop; track stash state in your orchestration.","Guard pop with `git stash list` so empty-stack pops are skipped.","Remove untracked files that collide with stashed paths before popping.","Upgrade PopStashConflictMsg matching if your git version words conflicts differently."],"tags":["git","stash","pop","go"],"backgroundTag":"git-stash-pop-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}