{"record":{"id":"0627a68e45162f63","repo":"plandex-ai/plandex","slug":"error-checking-out-branch-v","errorCode":null,"errorMessage":"error checking out branch: %v","messagePattern":"error checking out branch: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/locks.go","lineNumber":472,"sourceCode":"\t\t\t}\n\n\t\t}\n\t}()\n\n\t// check if git lock file exists\n\t// remove it if so\n\terr = gitRemoveIndexLockFileIfExists(getPlanDir(orgId, planId))\n\tif err != nil {\n\t\tlog.Printf(\"[Lock] %s | %s | Error removing lock file: %v\", planId, params.Reason, err)\n\t\treturn newLock.Id, fmt.Errorf(\"error removing lock file: %v\", err)\n\t}\n\n\tif branch != \"\" {\n\t\t// checkout the branch\n\t\terr = gitCheckoutBranch(getPlanDir(orgId, planId), branch)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"[Lock] %s | %s | Error checking out branch: %v\", planId, params.Reason, err)\n\t\t\treturn newLock.Id, fmt.Errorf(\"error checking out branch: %v\", err)\n\t\t}\n\t\tlog.Printf(\"[Lock] %s | %s | Checked out branch\", planId, params.Reason)\n\t}\n\n\treturn newLock.Id, nil\n}\n\nfunc deleteRepoLockDB(id, planId, reason string, numRetry int) error {\n\tstart := time.Now()\n\tgoroutineID := getGoroutineID()\n\n\tif locksVerboseLogging {\n\t\tlog.Printf(\"[Lock][Delete][%d] START delete lock %s at %v | reason: %s\", goroutineID, id, start, reason)\n\n\t\tdefer func() {\n\t\t\tlog.Printf(\"[Lock][Delete][%d] END delete lock took %v | reason: %s\", goroutineID, time.Since(start), reason)\n\t\t}()\n\t}","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/locks.go#L454-L490","documentation":"If the lock request specified a branch, lockRepoDB runs gitCheckoutBranch on the plan directory after acquiring the DB lock; failure yields 'error checking out branch'. The repo lock is held (lock id returned), but the working tree is not on the requested branch. The git error is wrapped in the message.","triggerScenarios":"gitCheckoutBranch fails: branch does not exist locally/remotely, uncommitted or untracked changes would be overwritten, detached HEAD conflicts, or the repo has a corrupt index.","commonSituations":"Requesting a branch that was force-deleted on the remote; leftover dirty working tree from a previously crashed build; branch name typo or case mismatch; repo shallow-cloned without the target ref.","solutions":["Read the wrapped git error — 'pathspec did not match' means the branch is missing, 'local changes would be overwritten' means a dirty tree","Run git status / git fetch in the plan directory to see the actual state","Stash, reset --hard, or re-clone the plan directory to clear a dirty/corrupt tree","Verify the requested branch name is correct and exists on the remote","Release the lock id returned with the error if you do not proceed"],"exampleFix":"// before\nid, err := lockRepoDB(ctx, orgId, planId, reason)\nif err != nil { return err }\n// after\nid, err := lockRepoDB(ctx, orgId, planId, reason)\nif err != nil {\n    if strings.Contains(err.Error(), \"error checking out branch\") && id != \"\" {\n        deleteRepoLockDB(id, planId, \"branch checkout failed\", 0)\n    }\n    return err\n}","handlingStrategy":"validation","validationCode":"cmd := exec.Command(\"git\", \"-C\", planDir, \"rev-parse\", \"--verify\", \"refs/heads/\"+branch)\nif err := cmd.Run(); err != nil {\n    return fmt.Errorf(\"branch %s does not exist in %s\", branch, planDir)\n}","typeGuard":"func branchExists(planDir, branch string) bool {\n    return exec.Command(\"git\", \"-C\", planDir, \"rev-parse\", \"--verify\", \"refs/heads/\"+branch).Run() == nil\n}","tryCatchPattern":"id, err := lockRepoDB(ctx, orgId, planId, reason)\nif err != nil {\n    if strings.Contains(err.Error(), \"error checking out branch\") && id != \"\" {\n        _ = deleteRepoLockDB(id, planId, \"checkout failed\", 0)\n    }\n    return err\n}","preventionTips":["Verify the branch exists (git fetch + rev-parse) before requesting the lock","Keep plan working trees clean (reset/stash after each build)","Avoid shallow clones if arbitrary branch checkout is needed","Release the returned lock id when aborting on checkout failure"],"tags":["git","branch","locking"],"backgroundTag":"git-checkout-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}