{"record":{"id":"ed258d19511bf8ed","repo":"plandex-ai/plandex","slug":"error-getting-branches","errorCode":null,"errorMessage":"Error getting branches: ","messagePattern":"Error getting branches: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/branches.go","lineNumber":63,"sourceCode":"\t\tReason:   \"list branches\",\n\t\tScope:    db.LockScopeRead,\n\t\tCtx:      ctx,\n\t\tCancelFn: cancel,\n\t}, func(repo *db.GitRepo) error {\n\t\tres, err := db.ListPlanBranches(repo, planId)\n\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tbranches = res\n\n\t\treturn nil\n\t})\n\n\tif err != nil {\n\t\tlog.Printf(\"Error getting branches: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting branches: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tjsonBytes, err := json.Marshal(branches)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error marshalling branches: %v\\n\", err)\n\t\thttp.Error(w, \"Error marshalling branches: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tlog.Println(\"Successfully retrieved branches\")\n\n\tw.Write(jsonBytes)\n}\n\nfunc CreateBranchHandler(w http.ResponseWriter, r *http.Request) {\n\tlog.Println(\"Received request for CreateBranchHandler\")","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/branches.go#L45-L81","documentation":"ListBranchesHandler wraps the branch listing (db.ListPlanBranches under a read-locked repo operation) and returns HTTP 500 with 'Error getting branches: <err>' when that operation fails. This is a server-side catch-all covering git repo access and database query failures while enumerating a plan's branches. The underlying error text is appended so the client can see the real cause.","triggerScenarios":"GET to the plan branches endpoint when: the plan's git repo is missing or corrupted, the database query for branches fails (connection dropped, table locked), the read lock on 'main' cannot be acquired before context cancellation, or the repo lock times out because another operation holds a write lock.","commonSituations":"Hitting the endpoint while another long-running plan operation holds the repo write lock; a crashed/plans volume missing so the git repo dir doesn't exist; Postgres restarted or maxing connections; planId pointing to a deleted plan whose repo was pruned.","solutions":["Check server logs for the wrapped underlying error to see whether it was a lock timeout, git error, or DB error","Verify the plan's git repo directory exists on the server volume and is not corrupted (git fsck)","Confirm the database is reachable and connections are not exhausted","Retry after in-flight write operations on the plan complete (locks are released)"],"exampleFix":"// before\nbranches, err := db.ListPlanBranches(repo, planId)\nif err != nil { return err }\n// after\nbranches, err := db.ListPlanBranches(repo, planId)\nif err != nil {\n    return fmt.Errorf(\"list plan branches: %w\", err) // preserves context for the 500 body\n}","handlingStrategy":"retry","validationCode":"// client: verify plan exists and is accessible before listing branches\nresp, _ := client.Get(planURL)\nif resp.StatusCode == 404 { return errors.New(\"plan not found; fix planId\") }","typeGuard":null,"tryCatchPattern":"// retry with backoff on 500, since lock contention is transient\nfor i := 0; i < 3; i++ {\n    resp, err := client.Get(branchesURL)\n    if err == nil && resp.StatusCode == 200 { break }\n    if resp != nil && resp.StatusCode < 500 { return err } // non-retryable\n    time.Sleep(time.Duration(1<<i) * time.Second)\n}","preventionTips":["Avoid running conflicting plan operations concurrently on the same plan","Monitor plan repo volume health and disk space","Alert on database connection pool saturation","Surface the wrapped error body to diagnose lock vs DB vs git causes"],"tags":["http-500","git","database","locking"],"backgroundTag":"git-repo-operation-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}