gitbutlerapp/gitbutler · error
No HEAD reference found for remote {remote_name}
Error message
No HEAD reference found for remote {remote_name} What it means
Thrown during default-target detection after a push remote was found but refs/remotes/<name>/HEAD does not exist. The code resolves that symbolic ref to learn the remote's default branch (like git symbolic-ref refs/remotes/origin/HEAD); find_reference fails when the ref was never written. A missing remote HEAD typically means no fetch has populated it yet or the ref was deleted.
Source
Thrown at crates/but-action/src/lib.rs:154
}
}
}
fn default_target_setting_if_none(ctx: &Context) -> anyhow::Result<()> {
if ctx.project_meta()?.target_ref.is_some() {
return Ok(());
}
// Lets do the equivalent of `git symbolic-ref refs/remotes/origin/HEAD --short` to guess the default target.
let repo = ctx.repo.get()?;
let remote_name = repo
.remote_default_name(gix::remote::Direction::Push)
.ok_or_else(|| anyhow::anyhow!("No push remote set or more than one remote"))?
.to_string();
let mut head_ref = repo
.find_reference(&format!("refs/remotes/{remote_name}/HEAD"))
.map_err(|_| anyhow::anyhow!("No HEAD reference found for remote {remote_name}"))?;
let target_ref_name = head_ref
.target()
.try_name()
.ok_or_else(|| anyhow::anyhow!("Remote HEAD for {remote_name} is not symbolic"))?
.to_owned();
let head_commit = head_ref.peel_to_commit()?;
ctx.set_project_meta(ProjectMeta {
target_ref: Some(target_ref_name),
target_commit_id: Some(head_commit.id),
push_remote: None,
})?;
Ok(())
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, EnumString, Default)]
#[serde(rename_all = "camelCase")]View on GitHub (pinned to caf1f223d3)
Solutions
- Run git remote set-head <remote> --auto (or simply git fetch <remote>) to create the symbolic HEAD, then retry
- If the remote repository is empty, push or fetch a default branch first so a HEAD exists
- Alternatively set the project's target branch explicitly to skip detection
Example fix
# before: refs/remotes/origin/HEAD missing -> "No HEAD reference found for remote origin" # after: recreate it, then retry git remote set-head origin --auto
Defensive patterns
Strategy: validation
Validate before calling
let head_ref = format!("refs/remotes/{remote_name}/HEAD");
if repo.find_reference(&head_ref).is_err() {
// populate it first: `git remote set-head <remote> --auto` or `git fetch <remote>`
} Prevention
- Always fetch right after adding a remote
- Run git remote set-head --auto in repo bootstrap scripts
- Set target_ref explicitly in automation
When it happens
Trigger: default_target_setting_if_none with target_ref unset: remote_default_name(Push) returns a name, but repo.find_reference("refs/remotes/<name>/HEAD") errs - common after adding a remote without fetching, or when the ref was pruned or never created by the clone tooling.
Common situations: git remote add without a following git fetch; shallow/partial clones missing the HEAD symref; repos where refs/remotes/origin/HEAD was deleted manually or by aggressive ref pruning; freshly mirrored repositories.
Related errors
- Remote HEAD for {remote_name} is not symbolic
- No push remote set or more than one remote
- DefaultTargetNotFound
- remote branch '{target_branch_ref}' not found
- Failed to communicate with LM Studio server: ${error instanc
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/bd4711c54fdeb8df.
Report an issue: GitHub.