gitbutlerapp/gitbutler · error
Expected to be in edit mode
Error message
Expected to be in edit mode
What it means
ensure_edit_mode (crates/gitbutler-operating-modes/src/lib.rs) reads the current operating mode and demands OperatingMode::Edit. The mode is derived from HEAD: edit mode means HEAD points at refs/heads/gitbutler/edit (EDIT_BRANCH_REF); the workspace ref means open-workspace mode; anything else (or detached HEAD, or unreadable edit metadata) is OutsideWorkspace. Calling an edit-mode-only API while in one of those other modes yields this error.
Source
Thrown at crates/gitbutler-operating-modes/src/lib.rs:223
Ok(operating_mode(ctx, perm)? == OperatingMode::OpenWorkspace)
}
pub fn ensure_open_workspace_mode(ctx: &Context, perm: &RepoShared) -> Result<()> {
if in_open_workspace_mode(ctx, perm)? {
Ok(())
} else {
bail!("Expected to be in open workspace mode")
}
}
pub fn in_edit_mode(ctx: &Context, perm: &RepoShared) -> Result<bool> {
Ok(matches!(operating_mode(ctx, perm)?, OperatingMode::Edit(_)))
}
pub fn ensure_edit_mode(ctx: &Context, perm: &RepoShared) -> Result<EditModeMetadata> {
match operating_mode(ctx, perm)? {
OperatingMode::Edit(edit_mode_metadata) => Ok(edit_mode_metadata),
_ => Err(anyhow!("Expected to be in edit mode")),
}
}
pub fn in_outside_workspace_mode(ctx: &Context, perm: &RepoShared) -> Result<bool> {
Ok(matches!(
operating_mode(ctx, perm)?,
OperatingMode::OutsideWorkspace(_)
))
}
View on GitHub (pinned to caf1f223d3)
Solutions
- Guard the call: check gitbutler_operating_modes::in_edit_mode(&ctx, &perm) first and only invoke edit-mode APIs when true
- Switch into edit mode through the app's flow (checkout of refs/heads/gitbutler/edit) before calling edit-only commands
- If HEAD should be the edit branch but is not, inspect `git symbolic-ref HEAD` and the edit-mode metadata under the project's GitButler dir
- For UI/backend code, surface mode state and disable edit-mode actions instead of firing them blindly
Example fix
// before
let meta = gitbutler_operating_modes::ensure_edit_mode(&ctx, &perm)?;
// after: check the predicate first and degrade gracefully
if !gitbutler_operating_modes::in_edit_mode(&ctx, &perm)? {
tracing::warn!("skipping edit-mode action: not in edit mode (HEAD != refs/heads/gitbutler/edit)");
return Ok(());
}
let meta = gitbutler_operating_modes::ensure_edit_mode(&ctx, &perm)?; Defensive patterns
Strategy: type-guard
Validate before calling
// non-fatal predicate check before edit-mode-only calls
if !gitbutler_operating_modes::in_edit_mode(&ctx, &perm)? {
return Ok(()); // or skip the feature in this mode
} Type guard
// in_edit_mode IS the type guard: OperatingMode -> bool narrowing
pub fn can_run_edit_mode_action(ctx: &Context, perm: &RepoShared) -> Result<bool> {
gitbutler_operating_modes::in_edit_mode(ctx, perm)
} Try / catch
match gitbutler_operating_modes::ensure_edit_mode(&ctx, &perm) {
Ok(meta) => run_edit_action(meta),
Err(err) if err.to_string().contains("Expected to be in edit mode") => {
tracing::warn!("mode mismatch — HEAD is not refs/heads/gitbutler/edit");
Ok(()) // degrade instead of failing the whole command
}
Err(err) => Err(err),
} Prevention
- Gate every edit-mode command with in_edit_mode() at dispatch time, not after
- Re-check the mode inside long-running jobs right before they touch edit state — the user may switch modes mid-flight
- Treat the mode as a state machine: subscribe to mode changes and enable/disable UI actions accordingly
When it happens
Trigger: Invoking edit-mode commands while HEAD is refs/heads/gitbutler/workspace (open workspace mode); HEAD on an ordinary branch or detached (outside workspace mode); edit-mode metadata unreadable, in which case operating_mode itself falls back to OutsideWorkspace; concurrent mode switches racing the call.
Common situations: A user (or the UI) exits edit mode while a background job still calls edit-mode APIs; automation that assumes edit mode without checking; the edit branch checked out but its metadata file damaged; race between opening a workspace and dispatching an edit command.
Related errors
- Expected to be in open workspace mode
- When using OpenRouter, you must provide a valid API key
- HTTP Error ${response.statusText}: ${text}
- Tearing off a branch requires a workspace common base
- Refusing to delete last named segment '{}' as it would leave
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/824e7a9ad2a44273.
Report an issue: GitHub.