gitbutlerapp/gitbutler · error · anyhow::Error

worktree manipulation is not enabled (featureFlags.worktreeM

Error message

worktree manipulation is not enabled (featureFlags.worktreeManipulation)

What it means

Worktree manipulation in but-api is experimental and opt-in: every command in crates/but-api/src/worktrees.rs (worktrees_list, worktree_set_archived, and the ChangeSource::Worktree commit paths via open_changes_source) calls ensure_worktree_manipulation_enabled() first, which fails unless the user setting featureFlags.worktreeManipulation is enabled. Nothing about the repository is wrong - the feature is simply switched off.

Source

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

    /// The branch the worktree has checked out, or `None` for a detached `HEAD`.
    #[serde(with = "but_serde::fullname_lossy_opt")]
    pub ref_name: Option<gix::refs::FullName>,
}

/// All listable linked worktrees, separated by archived state.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorktreeListing {
    /// Non-archived worktrees.
    pub active: Vec<Worktree>,
    /// Archived worktrees, hidden from the workspace but still on disk.
    pub archived: Vec<Worktree>,
}

/// Fail unless the user opted into worktree manipulation.
fn ensure_worktree_manipulation_enabled(ctx: &but_ctx::Context) -> Result<()> {
    if !ctx.settings.feature_flags.worktree_manipulation {
        bail!("worktree manipulation is not enabled (featureFlags.worktreeManipulation)");
    }
    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 {

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Enable the worktreeManipulation feature flag in GitButler settings, then retry
  2. If writing an integration, detect this error and prompt the user to opt in instead of retrying
  3. Otherwise avoid the worktree APIs - they are experimental and gated for a reason

Example fix

// before
const listing = await api.worktreesList(); // throws when flag off

// after: check the flag first (settings API) and guide the user
const flags = await api.getFeatureFlags?.() ?? {};
if (!flags.worktreeManipulation) {
  promptEnableExperimental('worktreeManipulation');
} else {
  const listing = await api.worktreesList();
}
Defensive patterns

Strategy: validation

Validate before calling

// Check the experimental flag before touching worktree APIs
const settings = await api.getSettings(); // or your settings transport
if (!settings.featureFlags?.worktreeManipulation) {
  promptEnableWorktreeManipulation();
} else {
  const listing = await api.worktreesList();
}

Try / catch

try {
  await api.worktreesList();
} catch (err) {
  if (String(err).includes('featureFlags.worktreeManipulation')) {
    showOptInNotice('Enable the experimental worktreeManipulation flag to use worktrees');
  } else throw err;
}

Prevention

When it happens

Trigger: Invoking worktrees_list(), worktree_set_archived(), or any commit-from-worktree flow through Tauri, the SDK, or CLI while settings.feature_flags.worktree_manipulation is false (the default). The check runs before any worktree access, so it fails fast and identically everywhere.

Common situations: Fresh install / default settings; SDK or CLI integrations probing worktree APIs without checking the opt-in; users who never enabled the experimental worktree support in GitButler settings.

Related errors


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