{"record":{"id":"112196a0785f220f","repo":"gitbutlerapp/gitbutler","slug":"head-is-detached","errorCode":null,"errorMessage":"HEAD is detached","messagePattern":"HEAD is detached","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-agentlog/src/environment.rs","lineNumber":385,"sourceCode":"                observation.observed_targets = fallback;\n            }\n            Ok(observation)\n        }\n        Err(error) => match current_branch_targets(repo) {\n            Ok(fallback) if !fallback.is_empty() => Ok(WorkspaceObservation {\n                stacks: Vec::new(),\n                observed_targets: fallback,\n                error_kind: Some(SnapshotErrorKind::Workspace),\n            }),\n            _ => Err(error),\n        },\n    }\n}\n\nfn current_branch_targets(repo: &gix::Repository) -> anyhow::Result<ObservedTargets> {\n    let head = repo.head()?;\n    let Some(ref_name) = head.referent_name() else {\n        anyhow::bail!(\"HEAD is detached\");\n    };\n    let full_ref_name = ref_name.to_string();\n    if !full_ref_name.starts_with(\"refs/heads/\") {\n        anyhow::bail!(\"HEAD does not point to a local branch\");\n    }\n    if is_workspace_ref_name(ref_name) {\n        anyhow::bail!(\"HEAD points to the GitButler workspace branch\");\n    }\n    let branch = BranchTarget {\n        key: format!(\"ref:{full_ref_name}\"),\n        name: ref_name.shorten().to_string(),\n    };\n    // Derive the PR association from the forge review cache rather than stored\n    // metadata. Synthesize a metadata entry carrying the resolved number so a\n    // branch with a cached PR is reported even without stored branch metadata.\n    let reviews = match resolve_branch_pr(repo, ref_name, &forge_prs_by_head(repo)) {\n        Some(pull_request) => {\n            let mut metadata = Branch::default();","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but-agentlog/src/environment.rs#L367-L403","documentation":"current_branch_targets in crates/but-agentlog/src/environment.rs resolves the current branch from HEAD to build ObservedTargets. If repo.head() returns a HEAD that is not a symbolic reference (no referent), it bails with \"HEAD is detached\" because branch targets cannot be determined from a detached HEAD.","triggerScenarios":"Calling current_branch_targets (via workspace_snapshot_with_current_branch_fallback) while the repo is in detached-HEAD state, e.g. after `git checkout <sha>` or a rebase in progress.","commonSituations":"Agent tooling runs inside a CI checkout pinned to a commit; a user checked out a tag or commit for inspection; mid-rebase states leave HEAD detached.","solutions":["Check out a local branch first: `git switch <branch>` (or `git switch -c <branch>` to keep the commits).","Skip the branch-target snapshot when HEAD is detached: test with `git symbolic-ref -q HEAD` before invoking.","Extend the caller to handle detached HEAD explicitly (record the commit id instead of a branch target)."],"exampleFix":"// before\nbut agentlog ...  # fails in detached HEAD\n// after\ngit switch -c work-from-detached\nbut agentlog ...","handlingStrategy":"fallback","validationCode":"# detect detached HEAD before running\ngit symbolic-ref -q HEAD >/dev/null 2>&1 || { echo \"HEAD is detached\"; exit 1; }","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"HEAD is detached\") => {\n        // fall back to commit-id-based snapshot or skip\n    }\n    r => r?,\n}","preventionTips":["Run agent tooling on a branch, not a bare commit checkout.","In CI, create a branch from the checkout SHA before running snapshots.","Check for rebase/checkout states that leave HEAD detached."],"tags":["git","detached-head","rust","state"],"backgroundTag":"git-command-failed","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}