{"record":{"id":"a0860e1ec7ebe434","repo":"gitbutlerapp/gitbutler","slug":"expected-to-be-in-open-workspace-mode","errorCode":null,"errorMessage":"Expected to be in open workspace mode","messagePattern":"Expected to be in open workspace mode","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/gitbutler-operating-modes/src/lib.rs","lineNumber":212,"sourceCode":"    let (outcome, conflict_kind) =\n        but_workspace::legacy::merge_worktree_with_workspace(ctx, gix_repo, &ws)?;\n    Ok(outcome\n        .conflicts\n        .iter()\n        .filter(|c| c.is_unresolved(conflict_kind))\n        .map(|c| c.ours.location().into())\n        .collect())\n}\n\npub fn in_open_workspace_mode(ctx: &Context, perm: &RepoShared) -> Result<bool> {\n    Ok(operating_mode(ctx, perm)? == OperatingMode::OpenWorkspace)\n}\n\npub fn ensure_open_workspace_mode(ctx: &Context, perm: &RepoShared) -> Result<()> {\n    if in_open_workspace_mode(ctx, perm)? {\n        Ok(())\n    } else {\n        bail!(\"Expected to be in open workspace mode\")\n    }\n}\n\npub fn in_edit_mode(ctx: &Context, perm: &RepoShared) -> Result<bool> {\n    Ok(matches!(operating_mode(ctx, perm)?, OperatingMode::Edit(_)))\n}\n\npub fn ensure_edit_mode(ctx: &Context, perm: &RepoShared) -> Result<EditModeMetadata> {\n    match operating_mode(ctx, perm)? {\n        OperatingMode::Edit(edit_mode_metadata) => Ok(edit_mode_metadata),\n        _ => Err(anyhow!(\"Expected to be in edit mode\")),\n    }\n}\n\npub fn in_outside_workspace_mode(ctx: &Context, perm: &RepoShared) -> Result<bool> {\n    Ok(matches!(\n        operating_mode(ctx, perm)?,\n        OperatingMode::OutsideWorkspace(_)","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/gitbutler-operating-modes/src/lib.rs#L194-L230","documentation":"`ensure_open_workspace_mode` guards the workspace-mode APIs (most virtual branch operations): it bails when the project's operating mode is not `OpenWorkspace`, which in practice means the project is still in edit mode. It is the mirror of `ensure_edit_mode` on the other side of the mode boundary.","triggerScenarios":"Calling open-workspace-only APIs (virtual branch create/update/apply and friends) while the project is in edit mode or before an edit-mode session was aborted.","commonSituations":"Programmatic workflows that enter edit mode and never exit; crashed edit-mode sessions leaving the mode set; tests that don't reset operating mode between cases.","solutions":["Abort edit mode first (`abort_and_return_to_workspace`, with force only after user confirmation), then retry the workspace operation","Check `in_open_workspace_mode(ctx, perm)?` before calling and surface a clear mode error to the user","If the app should never have been in edit mode here, investigate how the mode was left set"],"exampleFix":"// before\nensure_open_workspace_mode(&ctx, &perm)?; // bails while in edit mode\n\n// after\nif in_edit_mode(&ctx, &perm)? {\n    abort_and_return_to_workspace(&ctx, user_confirmed_discard(), &mut perm)?;\n}\nensure_open_workspace_mode(&ctx, &perm)?;","handlingStrategy":"validation","validationCode":"if !in_open_workspace_mode(&ctx, &perm)? {\n    return Err(anyhow::anyhow!(\"this operation requires open workspace mode\"));\n}","typeGuard":"fn is_workspace_op_allowed(mode: &OperatingMode) -> bool {\n    *mode == OperatingMode::OpenWorkspace\n}","tryCatchPattern":"match ensure_open_workspace_mode(&ctx, &perm) {\n    Err(err) if err.to_string().contains(\"open workspace mode\") => {\n        // abort edit mode first, then retry\n    }\n    other => other,\n}","preventionTips":["Always pair enter/exit of edit mode within the same workflow","Check the operating mode at the API boundary before dispatching workspace operations"],"tags":["rust","gitbutler","operating-mode","workspace","state-guard"],"backgroundTag":"wrong-operating-mode","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}