gitbutlerapp/gitbutler · error

`but land` requires an active GitButler workspace (`gitbutle

Error message

`but land` requires an active GitButler workspace (`gitbutler/workspace`). Switch into the workspace and try again.

What it means

`but land` only operates on a GitButler-managed workspace: the project must carry the `gitbutler/workspace` ref that the GitButler app creates when it adopts a repository. The handler checks `ws.kind.has_managed_ref()` before prompting and bails with this friendly message; the API layer enforces the same guard again before mutating anything.

Source

Thrown at crates/but/src/command/legacy/land/mod.rs:35

pub fn handle(
    ctx: &mut Context,
    out: &mut OutputChannel,
    branch_id: &str,
    yes: bool,
    no_ff: bool,
    whole_stack: bool,
) -> anyhow::Result<()> {
    // Resolve the branch identifier and read the target configuration. The managed-workspace guard
    // runs here for a friendly message before the prompt; the API enforces it again, along with the
    // bottom-segment, conflicted-commit, and triangular-remote guards, before mutating anything.
    let (branch_name, base_branch) = {
        let mut guard = ctx.exclusive_worktree_access();

        {
            let (_repo, ws, _db) = ctx.workspace_and_db_with_perm(guard.read_permission())?;
            if !ws.kind.has_managed_ref() {
                bail!(
                    "`but land` requires an active GitButler workspace (`gitbutler/workspace`). \
                     Switch into the workspace and try again."
                );
            }
        }

        let id_map = IdMap::new_from_context(ctx, guard.read_permission())?;
        let resolved_ids = id_map.parse_using_context(branch_id, ctx)?;
        if resolved_ids.is_empty() {
            bail!("Could not find branch: {branch_id}");
        }
        if resolved_ids.len() > 1 {
            bail!("Ambiguous branch '{branch_id}', matches multiple items");
        }

        let branch_name = match &resolved_ids[0] {
            CliId::Branch(branch) => branch.name.clone(),
            other => bail!("Expected a branch ID, got {}", other.kind_for_humans()),

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Open/adopt the project once in the GitButler app so the `gitbutler/workspace` ref exists.
  2. Run the command from the repository root GitButler manages; `but status` should list lanes there.
  3. If you do not want a GitButler workspace, land with plain git (merge/push) instead.
Defensive patterns

Strategy: validation

Validate before calling

# Require a GitButler workspace before land commands
git show-ref 2>/dev/null | grep -q 'gitbutler/workspace' || { echo 'not a GitButler workspace'; exit 2; }
but land "$branch" --yes

Prevention

When it happens

Trigger: Running `but land` in a plain git repository that was never opened/adopted by the GitButler app; in a repo whose workspace ref was deleted; from the wrong directory (a submodule, an unrelated clone, a nested repo).

Common situations: Trying the CLI against a repo used only with vanilla git; workspace refs removed by cleanup scripts or manual ref pruning; running land from a directory inside a different repository.

Related errors


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