gitbutlerapp/gitbutler · error · anyhow::Error
Cannot currently handle remotes as start position
Error message
Cannot currently handle remotes as start position
What it means
Thrown by but-graph's init (crates/but-graph/src/init/mod.rs:954) when the requested start position ref_name is a remote-tracking branch (Category::RemoteBranch, e.g., refs/remotes/origin/main). The code carries an explicit TODO: Git itself refuses to check out remote-tracking branches by name, and the initial traversal flags would need special setup (plus a guard against traversing the ref twice, once as tip and once by discovery). So today this input is rejected up front rather than mis-behaving later.
Source
Thrown at crates/but-graph/src/init/mod.rs:954
};
let Options {
collect_tags,
extra_target_commit_id,
commits_limit_hint: limit,
commits_limit_recharge_location: mut max_commits_recharge_location,
hard_limit,
dangerously_skip_postprocessing_for_debugging,
worktrees: _,
} = options;
let max_limit = Limit::new(limit);
if ref_name
.as_ref()
.is_some_and(|name| name.category() == Some(Category::RemoteBranch))
{
// TODO: see if this is a thing - Git doesn't like to checkout remote tracking branches by name,
// and if we should handle it, we need to setup the initial flags accordingly.
// Also we have to assure not to double-traverse the ref, once as tip and once by discovery.
bail!("Cannot currently handle remotes as start position");
}
let commit_graph = repo.commit_graph_if_enabled()?;
let shallow_commits = repo.shallow_commits()?;
let mut buf = Vec::new();
let configured_remote_tracking_branches =
remotes::configured_remote_tracking_branches(repo)?;
let initial_tips = initial_tips_from_tips(
repo,
tips,
&graph.project_meta,
extra_target_commit_id,
worktree_tips,
)?;
graph.traversal_tips = initial_tips.tips.clone();
let refs_by_id = repo.collect_ref_mapping_by_prefix(
[
"refs/heads/",View on GitHub (pinned to caf1f223d3)
Solutions
- Pass the local branch name instead (refs/heads/main); create it first if missing: `git branch main origin/main`
- Or peel the remote ref to a commit id and use that commit as the start position instead of a ref name
- If you actually want a detached start, resolve the remote ref to its OID and pass the commit
Example fix
// before
let graph = but_graph::init(repo, InitOptions { ref_name: Some("origin/main".into()), .. })?; // bails: RemoteBranch
// after
let oid = repo.find_reference("refs/remotes/origin/main")?.peel_to_commit()?.id();
let graph = but_graph::init(
repo,
InitOptions {
ref_name: Some("refs/heads/main".into()), // local branch
extra_target_commit_id: Some(oid), // remote tip as extra target
..Default::default()
},
)?; Defensive patterns
Strategy: validation
Validate before calling
// Reject or rewrite remote-tracking start positions before init
use but_graph::Category;
let ref_name = match ref_name {
Some(name) if name.category() == Some(Category::RemoteBranch) => {
// peel to the commit and use it instead of the remote ref
let oid = repo.find_reference(name.as_ref())?.peel_to_commit_in_place()?;
Some(repo.find_reference(main_branch_name)?.name().to_owned()) // local branch
.map(|n| (n, Some(oid)))
.map(|(n, o)| { extra_target_commit_id = o; n })
.unwrap()
}
other => other,
}; Type guard
fn is_remote_tracking(name: &gix::refs::FullName) -> bool {
name.category() == Some(but_graph::Category::RemoteBranch)
} Try / catch
match but_graph::init(repo, opts) {
Ok(g) => g,
Err(err) if err.to_string().contains("remotes as start position") => {
bail!("remote-tracking branches cannot start a graph; pass the local branch or a commit id")
}
Err(err) => return Err(err),
} Prevention
- Create the local branch after clone (git branch <name> <remote>/<name>) and pass refs/heads/<name>
- When automation derives a start ref from git plumbing, filter out refs/remotes/* before feeding but-graph
When it happens
Trigger: Building a graph with ref_name = Some("refs/remotes/origin/main") or the shorthand "origin/main"; tooling that resolves 'default branch' to the remote-tracking ref instead of a local branch; attempts to start a workspace directly from a fetched remote state.
Common situations: Fresh clones where the local branch has not been created yet and only origin/main exists; scripts feeding `git rev-parse --symbolic-full-name` output straight into but-graph; users expecting remote refs to behave like local branches.
Related errors
- Can't handle reference '{rn}' of category '{category:?}'
- Failed to find reference {ref_name} due to it being dropped
- BUG: {id} is queued
- handled above
- prefiltered
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/77ef871129815463.
Report an issue: GitHub.