gitbutlerapp/gitbutler · warning

target OID must exist when merge check is enabled

Error message

target OID must exist when merge check is enabled

What it means

Defensive expect in 'but branch list': the merge-status check (default on; disabled with --no-check) needs the workspace target's commit id to test whether branches merge cleanly into it. As with the ahead calculation, target_oid is resolved whenever '!empty || ahead || check_merge' holds and resolution failures propagate as errors before this point, so the expect is a wiring invariant rather than a reachable user-facing failure.

Source

Thrown at crates/but/src/command/legacy/branch/list.rs:205

    let has_more_branches = branches_to_show.len() > max_branches;
    let branches_to_show: Vec<_> = branches_to_show.into_iter().take(max_branches).collect();

    // Calculate commits ahead if requested
    let commits_ahead_map: Option<HashMap<String, usize>> = if ahead {
        Some(calculate_commits_ahead(
            ctx,
            target_oid.expect("target OID must exist when ahead calculation is enabled"),
            &branches_to_show,
        )?)
    } else {
        None
    };

    // Check merge status if requested
    let merge_status_map: Option<HashMap<String, bool>> = if check_merge {
        Some(check_branches_merge_cleanly(
            ctx,
            target_oid.expect("target OID must exist when merge check is enabled"),
            &applied_stacks,
            &branches_to_show,
        )?)
    } else {
        None
    };

    let allow_truncation = out.format().allows_truncation();
    if let Some(out) = out.for_json() {
        output_json(
            &applied_stacks,
            &branches_to_show,
            has_more_branches,
            &branch_review_map,
            commits_ahead_map.as_ref(),
            merge_status_map.as_ref(),
            ctx,
            out,

View on GitHub (pinned to 2497b8007a)

Solutions

  1. Update the resolution condition whenever a new flag consumes target_oid
  2. Maintainer: convert to an ok_or_else error naming --check as the requiring flag
  3. Cover the flag matrix (--no-check, --no-ahead, --empty) in CLI tests

Example fix

// before
target_oid.expect("target OID must exist when merge check is enabled")

// after
let target_oid = target_oid.ok_or_else(|| {
    anyhow::anyhow!("merge checking needs a resolvable workspace target branch; fetch the target ref first")
})?;
Defensive patterns

Strategy: validation

Validate before calling

// Ensure sync of the merge-check consumer with target resolution
// (unit-level: invoke the list handler with check_merge=true and a resolvable workspace)
let out = run_but(&["branch", "list"]).assert().success();
let out_no_check = run_but(&["branch", "list", "--no-check"]).assert().success();

Prevention

When it happens

Trigger: Only a refactor that enables check_merge handling while resolving target_oid under a narrower condition than list.rs:47 uses; user input alone cannot trigger it.

Common situations: Contributors changing flag semantics around target resolution; end users instead hit the propagated 'target unresolved' error when the workspace base branch is missing.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@2497b8007a (2026-08-17). Data as JSON: /api/errors/af0a8b4d957751b9. Report an issue: GitHub.