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

  1. Configure the default target (assign the base branch) via the but UI/CLI (`but branch`/assignment flow or set target metadata)
  2. Add a remote and a remote-tracking ref (`git remote add origin ...; git fetch`) then retry
  3. 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

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


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)