affaan-m/ECC · error · anyhow::Error

Cannot merge active session

Error message

Cannot merge active session {} while it is {}

What it means

The merge operation refuses to merge a session that is still active (Pending, Running, Idle, or Stale). Merging an active session's worktree could race with a live process writing to it, producing corrupt merges. Only sessions in a terminal state may be merged.

Solutions

  1. Wait for the session to reach a terminal state (Completed/Failed) before merging
  2. Cancel or stop the running session first, then merge
  3. Clean up Stale sessions (reap dead pids and finalize state) so they become mergeable
  4. Verify session state via resolve_session before invoking merge

Example fix

// before
merge_session(db, id)?;
// after
let session = resolve_session(db, id)?;
if matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale) {
    eprintln!("session {} still active ({:?}); waiting", id, session.state);
} else {
    merge_session(db, id)?;
}
Defensive patterns

Strategy: validation

Validate before calling

let session = resolve_session(db, id)?;
if matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale) {
    return Err(format!("session {} not mergeable in state {:?}", id, session.state));
}

Type guard

fn is_mergeable(s: &Session) -> bool { !matches!(s.state, SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale) }

Try / catch

match merge_session(db, id) {
    Err(e) if e.to_string().starts_with("Cannot merge active session") => retry_after_completion(id),
    other => other,
}

Prevention

When it happens

Trigger: Calling the merge-session API (manager.rs:1783) on a session whose state matches Pending | Running | Idle | Stale.

Common situations: Trying to merge while the agent process is still executing; a crashed session left in Idle/Stale state; a queued (Pending) session someone attempted to merge prematurely; UI showing a stale state where the session appears finished but is Stale.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/9102631c77e66c13. Report an issue: GitHub.

Appendix: source

Thrown at ecc2/src/session/manager.rs:1783

pub struct WorktreeRebaseOutcome {
    pub session_id: String,
    pub branch: String,
    pub base_branch: String,
    pub already_up_to_date: bool,
}

pub async fn merge_session_worktree(
    db: &StateStore,
    id: &str,
    cleanup_worktree: bool,
) -> Result<WorktreeMergeOutcome> {
    let session = resolve_session(db, id)?;

    if matches!(
        session.state,
        SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale
    ) {
        anyhow::bail!(
            "Cannot merge active session {} while it is {}",
            session.id,
            session.state
        );
    }

    let worktree = session
        .worktree
        .clone()
        .ok_or_else(|| anyhow::anyhow!("Session {} has no attached worktree", session.id))?;
    let outcome = crate::worktree::merge_into_base(&worktree)?;

    if cleanup_worktree {
        crate::worktree::remove(&worktree)?;
        db.clear_worktree(&session.id)?;
    }

    Ok(WorktreeMergeOutcome {

View on GitHub (pinned to 8321021c54)