gitbutlerapp/gitbutler · error
DefaultTargetNotFound
DefaultTargetNotFound
Error message
there is no default target
What it means
ProjectMeta::target_ref_or_err returns this DefaultTargetNotFound error when the project metadata has no target_ref configured. The target ref (the remote branch a local branch is based on, e.g. refs/remotes/origin/main) is required for operations that need to compare against the default branch. Callers like target_short_name and push_remote_name depend on it, so any operation that resolves branch metadata before a target was established hits this.
Solutions
- Configure the default target (assign the base branch) via the but UI/CLI (`but branch`/assignment flow or set target metadata)
- Add a remote and a remote-tracking ref (`git remote add origin ...; git fetch`) then retry
- Avoid calling *_or_err variants on projects known to lack a target; use the Option-returning target_ref() instead
Example fix
// before
let short = meta.target_short_name()?; // panics if no target
// after
if let Some(tref) = meta.target_ref() {
let short = meta.target_short_name()?;
} else {
assign_default_target(&mut meta)?;
} Defensive patterns
Strategy: validation
Validate before calling
if meta.target_ref().is_none() {
assign_default_target(&mut meta)?; // or bail early
} Type guard
fn has_target(meta: &ProjectMeta) -> bool { meta.target_ref().is_some() } Try / catch
match meta.target_ref_or_err() {
Ok(tref) => use(tref),
Err(e) if e.root_cause().to_string().contains("no default target") => configure_target()?,
Err(e) => return Err(e),
} Prevention
- Always configure the default target before operations that compare against it
- Ensure the repo has a remote and fetched remote-tracking refs
- Prefer Option-returning accessors (target_ref) when a missing target is acceptable
When it happens
Trigger: Calling target_ref_or_err (directly or via target_short_name/push_remote_name) on a ProjectMeta built before the target was recorded — e.g. in a repo with no remote tracking configuration or before first assignment of a default target.
Common situations: Freshly cloned-but-not-configured repos; repositories without any remote; running but commands before the first target/assignment was written; deleted remote-tracking branch leaving target_ref unset.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- No target branch is configured and none could be inferred…
- configured storage path
- configured storage path
- Failed to find remote branch's corresponding remote
- Local AI configuration requires running inside a git…
AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18).
Data as JSON: /api/errors/e2b07b652df7be37.
Report an issue: GitHub.
Appendix: source
Thrown at crates/but-core/src/ref_metadata.rs:300
match repo.find_reference(target_ref) {
Ok(mut target_ref) => {
if project_meta.target_commit_id.is_none()
&& let Ok(commit) = target_ref.peel_to_commit()
{
project_meta.target_commit_id = Some(commit.id);
}
}
Err(_) => project_meta.target_ref = None,
}
project_meta
}
impl ProjectMeta {
/// Return [`Self::target_ref`], or a [`DefaultTargetNotFound`](but_error::Code::DefaultTargetNotFound)
/// error if no target is configured.
pub fn target_ref_or_err(&self) -> Result<&gix::refs::FullName> {
self.target_ref.as_ref().ok_or_else(|| {
anyhow::anyhow!("there is no default target")
.context(but_error::Code::DefaultTargetNotFound)
})
}
/// Return [`Self::target_commit_id`], or a [`DefaultTargetNotFound`](but_error::Code::DefaultTargetNotFound)
/// error if no target commit is known.
pub fn target_commit_id_or_err(&self) -> Result<gix::ObjectId> {
self.target_commit_id.ok_or_else(|| {
anyhow::anyhow!("there is no default target commit")
.context(but_error::Code::DefaultTargetNotFound)
})
}
/// The name of the remote to push to: [`Self::push_remote`], falling back to the
/// remote behind [`Self::target_ref`].
///
/// If no configured remote matches the target ref, fall back to the first path component
/// after `refs/remotes/`, the textual remote name that legacy metadata stored verbatim.View on GitHub (pinned to 58e5313667)