{"record":{"id":"49d391036322c010","repo":"plandex-ai/plandex","slug":"error-checking-out-sha-v","errorCode":null,"errorMessage":"error checking out sha: %v","messagePattern":"error checking out sha: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/plans_changes.go","lineNumber":64,"sourceCode":"\tlog.Printf(\"locking with scope: %s\", scope)\n\n\tvar planState *shared.CurrentPlanState\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:   branch,\n\t\tScope:    scope,\n\t\tCtx:      ctx,\n\t\tCancelFn: cancel,\n\t\tReason:   \"get current plan state\",\n\t}, func(repo *db.GitRepo) error {\n\t\tvar err error\n\t\tif sha != \"\" {\n\t\t\terr = repo.GitCheckoutSha(sha)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error checking out sha: %v\", err)\n\t\t\t}\n\n\t\t\tdefer func() {\n\t\t\t\tcheckoutErr := repo.GitCheckoutBranch(branch)\n\t\t\t\tif checkoutErr != nil {\n\t\t\t\t\tlog.Printf(\"Error checking out branch: %v\\n\", checkoutErr)\n\t\t\t\t}\n\t\t\t}()\n\t\t}\n\n\t\tplanState, err = db.GetCurrentPlanState(db.CurrentPlanStateParams{\n\t\t\tOrgId:  auth.OrgId,\n\t\t\tPlanId: planId,\n\t\t})\n\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error getting current plan state: %v\", err)\n\t\t}","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/plans_changes.go#L46-L82","documentation":"Returned from the get-current-plan-state repo operation when repo.GitCheckoutSha(sha) cannot check out the requested commit SHA in the plan's git repo (e.g. fatal: bad object / reference not found). The ExecRepoOperation closure aborts and the handler responds 500 'Error getting current plan state: error checking out sha'.","triggerScenarios":"GET the plan-state endpoint with a sha path parameter that does not exist in the plan repo: an abbreviated/unknown SHA, a SHA that was garbage-collected or rewritten by a force-push/rebase, or a SHA from a different branch.","commonSituations":"Client caches a SHA from a previous session after the plan was reset or its history rewritten; typo in the SHA; asking for a SHA created after a repo re-init.","solutions":["Verify the SHA exists in the plan repo (e.g. git cat-file -t <sha>) and pass a full 40-char SHA","Omit the sha path segment to fetch the current branch state instead of a specific commit","Re-fetch the plan's latest SHAs from the server if the plan history was rewritten or reset","Check git repo health on the server (corrupt .git) if valid SHAs also fail"],"exampleFix":"// before: stale SHA from a rewritten history\nGET /plans/{planId}/branches/main/changes/abc1234\n// after: use current branch state\nGET /plans/{planId}/branches/main/changes","handlingStrategy":"fallback","validationCode":"// client-side sanity check before requesting a specific sha\nif (sha && !/^[0-9a-f]{7,40}$/.test(sha)) {\n  throw new Error('malformed sha: ' + sha)\n}","typeGuard":"function isPlausibleSha(s) {\n  return typeof s === 'string' && /^[0-9a-f]{7,40}$/.test(s)\n}","tryCatchPattern":"try {\n  state = await client.GetCurrentPlanState(planId, branch, sha)\n} catch (err) {\n  if (String(err.message).includes('error checking out sha')) {\n    state = await client.GetCurrentPlanState(planId, branch) // fall back to branch head\n  }\n}","preventionTips":["Re-fetch current SHAs from the server instead of caching across sessions (history may be rewritten)","Prefer fetching branch state; only pass sha when pinning a known-good commit","Send full 40-char SHAs to avoid ambiguity"],"tags":["git","plans","invalid-argument"],"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-12T22:17:10.623Z"}