{"record":{"id":"b14b28a377c90640","repo":"xai-org/grok-build","slug":"workspace-is-on-current-expected-expected","errorCode":null,"errorMessage":"workspace is on '{current}', expected '{expected}'","messagePattern":"workspace is on '(.+?)', expected '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/session/git.rs","lineNumber":2914,"sourceCode":"    if ok {\n        return Ok((PushStatus::Ok, out));\n    }\n    let lower = out.to_lowercase();\n    let status = if lower.contains(\"non-fast-forward\") || lower.contains(\"fetch first\") {\n        PushStatus::Conflict\n    } else {\n        PushStatus::Failed\n    };\n    Ok((status, out))\n}\n/// Refuse unless the workspace is on exactly `expected`. Detached HEAD\n/// reports \"HEAD\" and so never matches.\nasync fn ensure_on_branch(git_root: &Path, expected: Option<&str>) -> Result<()> {\n    let Some(expected) = expected else {\n        return Ok(());\n    };\n    let current = git_cli(git_root, &[\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]).await?;\n    anyhow::ensure!(\n        current == expected,\n        \"workspace is on '{current}', expected '{expected}'\"\n    );\n    Ok(())\n}\npub async fn commit(git_root: &Path, req: &GitCommitReq) -> Result<CommitResult> {\n    let start = std::time::Instant::now();\n    ensure_on_branch(git_root, req.expected_branch.as_deref()).await?;\n    if req.seed_default_excludes {\n        seed_default_excludes(git_root).await?;\n    }\n    if req.stage_all {\n        git_cli_mut(git_root, &[\"add\", \"-A\"]).await?;\n    }\n    let clean = req.stage_all\n        && !req.amend\n        && git_cli_raw(git_root, &[\"diff\", \"--cached\", \"--quiet\"])\n            .await?","sourceCodeStart":2896,"sourceCodeEnd":2932,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/session/git.rs#L2896-L2932","documentation":"`ensure_on_branch` guards the sync-base flow: it reads the workspace's current branch via `git rev-parse --abbrev-ref HEAD` and, if an expected branch was supplied and the checked-out branch differs, aborts with this message. This prevents merging/syncing from the wrong base. The doc comment notes detached HEAD reports \"HEAD\" and so never matches an expected branch name.","triggerScenarios":"Calling sync-base with `expected_branch` while the workspace is checked out on a different branch, or in detached-HEAD state (then `current` is the literal \"HEAD\").","commonSituations":"Agent or user left the workspace on a feature branch; a previous operation checked out a commit leaving detached HEAD; expected branch was renamed on the remote.","solutions":["Run `git checkout <expected-branch>` in the workspace and retry","If detached, `git switch -c <branch>` or `git checkout <expected>` first","Call the API without `expected_branch` if branch enforcement is not desired (it becomes a no-op check)","Compare `git rev-parse --abbrev-ref HEAD` with the expected branch before invoking"],"exampleFix":"// before\nsync_base(&git_root, req) // workspace on 'feature'\n// after\ngit_cli(&git_root, &[\"checkout\", \"main\"]).await?;\nsync_base(&git_root, req)","handlingStrategy":"validation","validationCode":"let cur = String::from_utf8(Command::new(\"git\").args([\"rev-parse\",\"--abbrev-ref\",\"HEAD\"]).current_dir(git_root).output()?.stdout)?.trim().to_string();\nif let Some(expected) = expected_branch {\n    if cur != expected { return Err(format!(\"on {cur}, expected {expected}; checkout first\")); }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always check the current branch before sync operations","Avoid detached-HEAD states; use `git switch` for named branches","Pass expected_branch only when you actually enforce it"],"tags":["git","branch-state","precondition"],"backgroundTag":"wrong-branch-checked-out","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}