{"record":{"id":"fd83abaf03516b44","repo":"plandex-ai/plandex","slug":"cannot-delete-main-branch","errorCode":null,"errorMessage":"Cannot delete main branch","messagePattern":"Cannot delete main branch","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"app/server/handlers/branches.go","lineNumber":180,"sourceCode":"\n\tauth := Authenticate(w, r, true)\n\tif auth == nil {\n\t\treturn\n\t}\n\n\tvars := mux.Vars(r)\n\tplanId := vars[\"planId\"]\n\tbranch := vars[\"branch\"]\n\n\tlog.Println(\"planId: \", planId)\n\n\tif authorizePlan(w, planId, auth) == nil {\n\t\treturn\n\t}\n\n\tif branch == \"main\" {\n\t\tlog.Println(\"Cannot delete main branch\")\n\t\thttp.Error(w, \"Cannot delete main branch\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tctx, cancel := context.WithCancel(r.Context())\n\n\terr := db.ExecRepoOperation(db.ExecRepoOperationParams{\n\t\tOrgId:    auth.OrgId,\n\t\tUserId:   auth.User.Id,\n\t\tPlanId:   planId,\n\t\tBranch:   \"main\",\n\t\tReason:   \"delete branch\",\n\t\tScope:    db.LockScopeWrite,\n\t\tCtx:      ctx,\n\t\tCancelFn: cancel,\n\t}, func(repo *db.GitRepo) error {\n\t\terr := repo.GitDeleteBranch(branch)\n\t\treturn err\n\t})","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/branches.go#L162-L198","documentation":"DeleteBranchHandler explicitly rejects deletion of the 'main' branch, returning HTTP 400 'Cannot delete main branch'. This is a deliberate business-rule guard: main is the plan's primary branch and always kept. It is a static validation, not an unexpected failure.","triggerScenarios":"DELETE to the branch endpoint with branch path variable exactly equal to \"main\". No other condition produces this error.","commonSituations":"A client or script iterating all branches and deleting each without excluding main; a UI bug passing the wrong branch variable; manual API testing with main in the path.","solutions":["Exclude 'main' from any bulk-delete loop before calling the delete endpoint","Fix the client to pass the intended non-main branch in the URL path","Treat this as an expected 400 in client code and skip main silently"],"exampleFix":"// before\nfor _, b := range branches {\n    client.DeleteBranch(planId, b)\n}\n// after\nfor _, b := range branches {\n    if b != \"main\" {\n        client.DeleteBranch(planId, b)\n    }\n}","handlingStrategy":"validation","validationCode":"// client: never attempt to delete main\nif branch == \"main\" {\n    return errors.New(\"refusing to delete main branch\")\n}","typeGuard":"func isDeletable(branch string) bool { return branch != \"main\" }","tryCatchPattern":null,"preventionTips":["Filter 'main' out of bulk-delete lists before iterating","Double-check the branch variable you pass in the URL path","Handle 400 for this case gracefully in UI (show 'main is protected')","Add client-side guard tests for protected branch names"],"tags":["validation","http-400","branch","business-rule"],"backgroundTag":"protected-branch-deletion","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"}