gitbutlerapp/gitbutler · error · anyhow::Error

Worktree {name} is archived

Error message

Worktree {name} is archived

What it means

active_worktree() resolves a linked worktree by its stable name (directory under $GIT_COMMON_DIR/worktrees/) and rejects archived ones: archived worktrees are hidden from the workspace graph, so operations against them could not be materialized. The lookup first fails with 'Worktree {name} does not exist' for unknown names; an existing-but-archived worktree fails here, before the follow-up 'no usable HEAD' check.

Source

Thrown at crates/but-api/src/worktrees.rs:68

    }
    Ok(())
}

/// Look up the *active* linked worktree named `name`.
///
/// Every command here operates on active worktrees only - an archived one is
/// hidden from the graph, so operations against it could not be materialized.
///
/// Must not be called while a database handle is borrowed, see
/// [`but_ctx::Context::worktrees_with_state()`].
fn active_worktree(ctx: &but_ctx::Context, name: &str) -> Result<WorktreeEntry> {
    let worktree = ctx
        .worktrees_with_state()?
        .into_iter()
        .find(|worktree| worktree.name == name.as_bytes())
        .with_context(|| format!("Worktree {name} does not exist"))?;
    if worktree.archived {
        bail!("Worktree {name} is archived");
    }
    if ctx.worktree_head(worktree.name.as_bstr())?.is_none() {
        // Unborn, workspace-ref checkout, or broken - nothing to operate on.
        bail!("Worktree {name} has no usable HEAD");
    }
    Ok(worktree)
}

/// Open the checkout that `source` reads its changes from, returning its stable
/// name along with a plain from-disk open of it, or `None` for the main worktree.
///
/// Callers turn this into a [`ChangeSource`](but_workspace::commit::ChangeSource)
/// for the duration of an editor-backed operation.
///
/// Must not be called while a database handle is borrowed, see
/// [`but_ctx::Context::worktrees_with_state()`].
pub(crate) fn open_changes_source(
    ctx: &but_ctx::Context,

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Unarchive it first: worktree_set_archived(name, false), then retry the operation
  2. Refresh with worktrees_list() and only operate on names from listing.active
  3. Drop the stale entry from your UI/state when this fires - the worktree is intentionally hidden

Example fix

// before
await someWorktreeOperation(name); // name was archived since listing

// after
const listing = await api.worktreesList();
if (listing.active.some(w => w.name === name)) {
  await someWorktreeOperation(name);
} else if (listing.archived.some(w => w.name === name)) {
  await api.worktreeSetArchived(name, false); // opt back in, then operate
}
Defensive patterns

Strategy: validation

Validate before calling

// Only operate on names from the active section of a fresh listing
const listing = await api.worktreesList();
const isActive = (name: string) => listing.active.some(w => w.name === name);
if (!isActive(name)) throw new Error(`worktree ${name} is archived or gone`);

Type guard

interface WorktreeRef { name: string; archived: boolean }
function isOperableWorktree(w: WorktreeRef, name: string): boolean {
  return w.name === name && !w.archived;
}

Try / catch

try {
  await someWorktreeOperation(name);
} catch (err) {
  if (String(err).includes('is archived')) {
    await api.worktreeSetArchived(name, false); // opt back in if intended
    await someWorktreeOperation(name);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing the name of a currently archived worktree to any worktree command (set head, commit from ChangeSource::Worktree('name'), etc.), or a race where the worktree was archived between your worktrees_list() call and the operation.

Common situations: UI holding a stale listing after the user archived worktrees elsewhere (projects predating GitButler worktree support often archive en masse); scripts iterating an old listing; forgetting that archived entries live in listing.archived, not listing.active.

Related errors


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