{"record":{"id":"753a8a5f4abcf3ce","repo":"gitbutlerapp/gitbutler","slug":"you-are-in-conflict-resolution-mode-finish-with-but-resolve","errorCode":null,"errorMessage":"You are in conflict resolution mode. Finish with `but resolve finish` or cancel with `but resolve cancel` first.","messagePattern":"You are in conflict resolution mode\\. Finish with `but resolve finish` or cancel with `but resolve cancel` first\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/but/src/command/legacy/resolve.rs","lineNumber":882,"sourceCode":"    out: &mut OutputChannel,\n    commit: Option<&str>,\n    target: &str,\n    flags: ResolutionFlags,\n    mut read: impl std::io::Read,\n) -> Result<()> {\n    use but_api::resolve::{HunkResolution, ResolutionSpec};\n\n    let ResolutionFlags {\n        ours,\n        theirs,\n        ai,\n        file,\n    } = flags;\n\n    let t = theme::get();\n    let mode = operating_mode(ctx)?.operating_mode;\n    if matches!(mode, OperatingMode::Edit(_)) {\n        bail!(\n            \"You are in conflict resolution mode. Finish with `but resolve finish` or cancel with `but resolve cancel` first.\"\n        );\n    }\n    let Some(conflict_target) = target_conflicted_commit(ctx, commit)? else {\n        bail!(\"No conflicted commits found.\");\n    };\n    let commit_oid = conflict_target.commit_oid;\n\n    // Split a trailing `:<number>` off the target; everything else is the path.\n    let (path, hunk) = match target.rsplit_once(':') {\n        Some((path, number))\n            if !number.is_empty() && number.bytes().all(|b| b.is_ascii_digit()) =>\n        {\n            (path, Some(number.parse::<usize>()?))\n        }\n        _ => (target, None),\n    };\n","sourceCodeStart":864,"sourceCodeEnd":900,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/crates/but/src/command/legacy/resolve.rs#L864-L900","documentation":"Thrown by apply_resolutions when the operating mode is Edit (i.e. an edit/conflict-resolution session is already active). Applying resolutions requires a clean state; the user must finish or cancel the current session first. The message spells out both escape commands.","triggerScenarios":"Running `but resolve` (apply_resolutions) while the context's operating_mode is OperatingMode::Edit — an unfinished `but edit`/resolution session.","commonSituations":"A previous `but resolve` or edit session was left open (crashed terminal, forgotten session); users then try to apply new resolutions on top.","solutions":["Run `but resolve finish` to complete the active session.","Or run `but resolve cancel --force`/`cancel` to abort it, then retry.","Check state with `but status`."],"exampleFix":"// before\nbut resolve abc123 file.rs --ours\n// after\nbut resolve finish && but resolve abc123 file.rs --ours","handlingStrategy":"validation","validationCode":"const mode = getOperatingMode();\nif (mode === 'edit') { await exec('but resolve finish'); } // or cancel\nawait butResolve(commit, path, args);","typeGuard":"const isEditMode = (m: OperatingMode) => m === 'edit';","tryCatchPattern":"try { await butResolve(...) } catch (e) { if (String(e).includes('conflict resolution mode')) { await exec('but resolve finish'); retry(); } }","preventionTips":["Always finish or cancel resolution sessions before new commands.","Wrap scripted resolve sequences with finish/cancel cleanup.","Check operating mode via `but status` before applying resolutions."],"tags":["cli","git","conflict-resolution","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}