gitbutlerapp/gitbutler · error · anyhow::Error

Couldn't find workspace head.

Error message

Couldn't find workspace head.

What it means

`tear_off_branch` needs the workspace tip commit to anchor the graph rewrite (`editor.select_commit(workspace_head)`); if `workspace.tip_commit()` returns None it bails with this message. It occurs after the single-segment early-return, so the workspace has multiple segments but no resolvable tip.

Source

Thrown at crates/but-workspace/src/branch/move_branch.rs:100

            }
        };

        let mut ws_meta = workspace.metadata.clone();

        let (source_stack, subject_segment) = source;

        if source_stack.segments.len() == 1 {
            // There's only one branch in the source stack. Nothing to do.
            return Ok(Outcome {
                rebase: editor.rebase()?,
                ws_meta,
                new_tip: None,
                branch_stack_order: None,
            });
        }

        let Some(workspace_head) = workspace.tip_commit().map(|commit| commit.id) else {
            bail!("Couldn't find workspace head.")
        };
        let head_selector = editor
            .select_commit(workspace_head)
            .context("Failed to find the workspace head in the graph.")?;

        let Some(lower_bound_ref) = workspace
            .lower_bound_segment_id
            .map(|segment_id| &workspace.graph[segment_id])
            .and_then(|segment| segment.ref_name())
        else {
            bail!("Tearing off a branch requires a workspace common base");
        };

        let target_selector = editor
            .select_reference(lower_bound_ref)
            .context("Failed to find target reference in graph.")?;

        let DisconnectParameters {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Fetch/repair the missing objects (`git fetch --unshallow` or restore from a remote/pack) and rebuild the workspace graph, then retry.
  2. If the workspace tip is genuinely lost, re-establish the workspace (repair flow / re-create workspace commit) before moving branches.
  3. Pre-check `workspace.tip_commit().is_some()` and block the move action with a clearer recovery message.
Defensive patterns

Strategy: validation

Validate before calling

if workspace.tip_commit().is_none() {
    anyhow::bail!("workspace has no resolvable tip commit; fetch/repair missing objects before moving branches");
}

Type guard

fn workspace_has_resolvable_tip(ws: &but_graph::Workspace) -> bool {
    ws.tip_commit().is_some()
}

Try / catch

if let Err(err) = move_branch::tear_off_branch(editor, &branch, None) {
    if err.to_string().contains("workspace head") {
        // workspace tip object missing: repair objects (fetch/unshallow) and rebuild the graph
    }
}

Prevention

When it happens

Trigger: A multi-segment workspace whose tip commit cannot be resolved — workspace ref points at a missing/unreadable commit object (pruned, shallow/incomplete clone, corrupted odb), or the graph's tip metadata is absent after an interrupted update.

Common situations: Partial/shallow clones missing workspace objects; `git gc --prune` removing the workspace commit; interrupted workspace writes leaving refs pointing at absent objects.

Related errors


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