{"record":{"id":"4a725a4494d03ae4","repo":"xai-org/grok-build","slug":"git-checkout-failed","errorCode":null,"errorMessage":"git checkout {} failed: {}","messagePattern":"git checkout (.+?) failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-fast-worktree/src/git/checkout.rs","lineNumber":88,"sourceCode":"            \"git clean {} failed: {}\",\n            flags,\n            String::from_utf8_lossy(&output.stderr)\n        );\n    }\n\n    Ok(())\n}\n\n/// Run `git checkout <ref>`. Blocking.\npub(crate) fn checkout_ref(worktree_path: &Path, git_ref: &str) -> Result<()> {\n    let output = git_command()\n        .current_dir(worktree_path)\n        .args([\"checkout\", git_ref])\n        .output()\n        .context(\"failed to run git checkout\")?;\n\n    if !output.status.success() {\n        anyhow::bail!(\n            \"git checkout {} failed: {}\",\n            git_ref,\n            String::from_utf8_lossy(&output.stderr)\n        );\n    }\n\n    tracing::debug!(path = %worktree_path.display(), git_ref = %git_ref, \"git checkout\");\n    Ok(())\n}\n\n/// Whether `git diff-index --quiet HEAD` reports differences (tracked-only, far\n/// cheaper than `git status`). `cached` adds `--cached`, comparing the index to\n/// `HEAD` and skipping the working-tree stat walk. Only ever over-reports (an\n/// error is treated as dirty), so a `false` result is safe to skip the reset on.\n/// Blocking.\n#[cfg_attr(not(target_os = \"linux\"), allow(dead_code))]\nfn diff_index_dirty(worktree_path: &Path, cached: bool) -> Result<bool> {\n    let mut cmd = git_command();","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-fast-worktree/src/git/checkout.rs#L70-L106","documentation":"`checkout_ref` runs `git checkout <ref>` in the worktree and bails with this message (ref plus git's stderr) when the command exits non-zero. Git refused the checkout, so the worktree remains on its previous ref/state.","triggerScenarios":"Calling `checkout_ref` with a ref that doesn't exist, when untracked files would be overwritten by checkout, when the index is locked, or when the worktree's git metadata is invalid.","commonSituations":"Typo'd or deleted branch/tag names; local untracked/modified files conflicting with the target ref; shallow or partial clones lacking target objects; concurrent git operations leaving `index.lock`; detached-HEAD worktree restrictions.","solutions":["Read git's stderr in the message — it distinguishes 'unknown revision', 'would be overwritten', and lock errors.","Verify the ref exists (`git rev-parse --verify <ref>`) and fetch it if missing before retrying.","Clear conflicting state: commit/stash or remove untracked files that block the checkout (`git clean`/`git stash -u`), or checkout with a reset flow.","Remove a stale `index.lock` if no git process is running, then retry.","Fetch missing objects for shallow/partial clones (`git fetch origin <ref>`) and retry."],"exampleFix":"// before\n// untracked build.log would be overwritten by target branch\ncheckout_ref(worktree, \"main\")?; // git checkout main failed: untracked working tree files would be overwritten\n// after\nrun_in(worktree, &[\"git\", \"clean\", \"-fd\"]); // or stash untracked files\ncheckout_ref(worktree, \"main\")?;\n","handlingStrategy":"try-catch","validationCode":"use std::process::Command;\nuse std::path::Path;\nfn can_checkout(worktree: &Path, git_ref: &str) -> bool {\n    let ref_ok = Command::new(\"git\").current_dir(worktree)\n        .args([\"rev-parse\", \"--verify\", \"--quiet\", git_ref])\n        .output().map(|o| o.status.success()).unwrap_or(false);\n    let no_lock = !worktree.join(\".git\").join(\"index.lock\").exists();\n    ref_ok && no_lock\n}","typeGuard":null,"tryCatchPattern":"match checkout_ref(worktree, git_ref) {\n    Err(e) if e.to_string().contains(\"git checkout\") => {\n        eprintln!(\"checkout failed: {e}\"); // stderr embedded\n        // clean/stash blockers or fetch the ref, then retry once\n    }\n    r => r?,\n}","preventionTips":["Verify the ref exists and is fetched before checking out","Run git clean or stash before switching refs so untracked files don't block checkout","Remove stale index.lock files after crashed git operations","Prefer unique, fully qualified refs (refs/heads/main) to avoid ambiguity"],"tags":["git","checkout","worktree","external-command"],"backgroundTag":"git-command-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}