gitbutlerapp/gitbutler · error · anyhow::Error

Target ref required for remote url

Error message

Target ref required for remote url

What it means

`remote_url_with_fallback()` derives a fetch URL from the workspace/stack's `target_ref`; if that field is `None` it bails immediately with 'Target ref required for remote url'. Unlike sibling methods (`target_ref_or_err`) it does not attach a `DefaultTargetNotFound` code — it's a plain precondition failure: the metadata was never populated with a target.

Source

Thrown at crates/but-core/src/ref_metadata.rs:348

            .category_and_short_name()
            .with_context(|| format!("failed to determine remote for branch {target_ref}"))?;
        if category != gix::refs::Category::RemoteBranch {
            bail!("failed to determine remote for non remote-tracking branch {target_ref}");
        }
        let slash_pos = short_name.find_byte(b'/').with_context(|| {
            format!("remote tracking branch {target_ref} didn't have '/' in its short name")
        })?;
        let remote_name = short_name[..slash_pos].to_str_lossy().into_owned();
        tracing::warn!(
            "remote '{remote_name}' of target ref {target_ref} is not configured in git config"
        );
        Ok(remote_name)
    }

    /// Get the fetch URL of the remote behind [`Self::target_ref`].
    pub fn remote_url_with_fallback(&self, repo: &gix::Repository) -> Result<String> {
        let Some(target_ref) = self.target_ref.as_ref() else {
            bail!("Target ref required for remote url")
        };
        let remote_names = repo.remote_names();
        let (remote_name, _short_name) =
            extract_remote_name_and_short_name(target_ref.as_ref(), &remote_names).context(
                format!("failed to determine remote for branch {target_ref}"),
            )?;
        let remote = repo.find_remote(remote_name.as_str()).context(format!(
            "failed to find remote {remote_name} for branch {target_ref}"
        ))?;
        remote
            .url(gix::remote::Direction::Fetch)
            .map(|url| url.to_bstring().to_string())
            .context(format!("failed to get fetch url for remote {remote_name}"))
    }

    /// The URL to push to, inferred by the [`Self::push_remote`] property.
    ///
    /// Falls back to the fetch URL of the remote behind [`Self::target_ref`] if

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Guard the call: only ask for the remote URL when `target_ref` is present (use `target_ref_or_err()`-style checks to surface a proper DefaultTargetNotFound to the UI).
  2. Complete onboarding so the target ref is set before any URL-dependent feature (push, forge integration) runs.
  3. If the target was lost, re-select the target branch in GitButler to repopulate `target_ref`.

Example fix

// before
let url = meta.remote_url_with_fallback(&repo)?;

// after
let url = meta
    .target_ref
    .as_ref()
    .map(|_| meta.remote_url_with_fallback(&repo))
    .transpose()?
    .unwrap_or_else(|| fallback_url.clone());
Defensive patterns

Strategy: validation

Validate before calling

// Rust — only ask for the remote URL when a target ref exists
if meta.target_ref.is_none() {
    // skip URL-dependent features; complete onboarding instead of erroring
    return Ok(UserAction::SelectTargetBranch);
}
let url = meta.remote_url_with_fallback(&repo)?;

Type guard

fn has_target_ref(meta: &but_core::ref_metadata::StackMetadata) -> bool {
    meta.target_ref.is_some()
}

Try / catch

match meta.remote_url_with_fallback(&repo) {
    Ok(url) => url,
    Err(err) if err.to_string().contains("Target ref required") => {
        fallback_url.clone() // or trigger target selection flow
    }
    Err(err) => return Err(err),
}

Prevention

When it happens

Trigger: Calling `remote_url_with_fallback(&repo)` on metadata whose `target_ref` is None — a workspace or stack that hasn't completed onboarding, an entry created but never targeted, or a caller holding partially-initialized ref metadata.

Common situations: Projects added but never assigned a target branch; tests constructing ref metadata by hand without a target; code paths that run right after workspace creation before the first fetch.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/71cd7783f23f33cc. Report an issue: GitHub.