{"record":{"id":"06eae818c234e3df","repo":"gitbutlerapp/gitbutler","slug":"cannot-unapply-workspace-reference-by-checking-out","errorCode":null,"errorMessage":"Cannot unapply workspace reference by checking out conflicted commit at '{}'","messagePattern":"Cannot unapply workspace reference by checking out conflicted commit at '(.+?)'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but-workspace/src/branch/unapply.rs","lineNumber":752,"sourceCode":"\n    /// Check out `ref_to_checkout` using the workspace traversal entrypoint as the\n    /// current worktree/index source.\n    ///\n    /// `ws` must be the workspace projection for the currently checked-out `HEAD`.\n    /// Its graph entrypoint is therefore the commit the index and worktree are\n    /// expected to match before checkout. This matters when `HEAD` points at a\n    /// stack segment inside the workspace rather than the workspace tip.\n    ///\n    /// The helper only updates the index/worktree according to `options`; callers\n    /// remain responsible for any subsequent `HEAD`, reference, metadata, and\n    /// projection updates.\n    fn safe_checkout_ref_to_checkout(\n        repo: &gix::Repository,\n        ref_to_checkout: &RefToCheckout,\n        options: but_core::worktree::checkout::Options,\n    ) -> anyhow::Result<but_core::worktree::checkout::Outcome> {\n        if but_core::Commit::from_id(ref_to_checkout.commit_id.attach(repo))?.is_conflicted() {\n            bail!(\n                \"Cannot unapply workspace reference by checking out conflicted commit at '{}'\",\n                ref_to_checkout.ref_name.shorten()\n            );\n        }\n        safe_checkout(repo, ref_to_checkout.commit_id, options)\n    }\n\n    /// Return the commit the workspace ref should point to when no workspace merge commit remains.\n    ///\n    /// A single remaining future tip is preferred. Otherwise, an empty workspace falls back to the\n    /// resolved target or the workspace lower bound.\n    fn commit_to_point_workspace_ref_to_after_unapply(\n        ws: &but_graph::Workspace,\n        future_workspace_tips: &[crate::commit::merge::Tip],\n    ) -> anyhow::Result<gix::ObjectId> {\n        if let Some(tip) = future_workspace_tips.first() {\n            return Ok(tip.commit_id);\n        }","sourceCodeStart":734,"sourceCodeEnd":770,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/caf1f223d3cfb94488c9198ad34487c6006c648f/crates/but-workspace/src/branch/unapply.rs#L734-L770","documentation":"The workspace-reference flavor of the conflicted-commit guard: when unapplying the workspace reference itself, the commit that would be checked out (RefToCheckout.commit_id) is conflicted. The message names the ref whose commit is conflicted so users can locate it. As with the sibling error, resolve conflicts first — no checkout happens when this fires.","triggerScenarios":"Calling unapply on the workspace reference (e.g. with a PreventUnnecessaryWorkspaceReferences disposition) when ref_to_checkout_after_workspace_unapply() selected a commit that but_core reports as conflicted.","commonSituations":"Dissolving a workspace whose remaining tip or target commit still contains conflict markers; unapplying the workspace ref right after a conflicted sync.","solutions":["Resolve conflicts on the named ref (or remove/undo the conflicted commit) and retry the workspace unapply.","Choose a different target to switch to by fixing the workspace state (integrate or unapply conflicted stacks first).","Fall back to GitButler's UI flow, which forces conflict resolution before workspace dissolution."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"use but_core::Commit;\nlet ref_to_checkout = ref_to_checkout_after_workspace_unapply(&ws)?;\nif Commit::from_id(ref_to_checkout.commit_id.attach(repo))?.is_conflicted() {\n    // the commit we would land on is conflicted: resolve or pick another target first\n    return prompt_conflict_resolution();\n}","typeGuard":null,"tryCatchPattern":"match unapply(repo, meta, &ws, ws_ref, opts) {\n    Err(err) if err.to_string().contains(\"conflicted commit at\") => {\n        ui::error(\"Resolve conflicts on the target branch before dissolving the workspace\");\n        Ok(default_outcome())\n    }\n    other => other,\n}","preventionTips":["Resolve conflicts on remaining stacks before dissolving a workspace.","Check the future checkout target with is_conflicted() in workspace-dissolution flows.","Integrate or unapply conflicted stacks first."],"tags":["gitbutler","unapply","workspace-ref","merge-conflict","rust"],"backgroundTag":"conflicted-commit-checkout","analyzedSha":"caf1f223d3cfb94488c9198ad34487c6006c648f","analyzedAt":"2026-08-20T07:55:40.983Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}