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

Cannot rebase active session

Error message

Cannot rebase active session {} while it is {}

What it means

The rebase operation refuses to rebase a session that is still active (Pending, Running, Idle, or Stale). Rebasing an active session's worktree would race with the live process, corrupting the rebase or the session's work. Only sessions in terminal states may be rebased.

Solutions

  1. Wait for the session to finish before rebasing
  2. Stop/cancel the session, wait for terminal state, then rebase
  3. Reap Stale sessions and finalize their state before rebase
  4. Gate rebase triggers on session state checks

Example fix

// before
rebase_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 ({:?}); deferring rebase", id, session.state);
} else {
    rebase_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 rebaseable in state {:?}", id, session.state));
}

Type guard

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

Try / catch

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

Prevention

When it happens

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

Common situations: Triggering rebase onto an updated main branch while the agent is still working; crashed sessions left in Idle/Stale; attempting rebase on a queued session; automation pipelines firing rebase before session completion.

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/3dc226630172af1a. Report an issue: GitHub.

Appendix: source

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

    }

    Ok(WorktreeMergeOutcome {
        session_id: session.id,
        branch: outcome.branch,
        base_branch: outcome.base_branch,
        already_up_to_date: outcome.already_up_to_date,
        cleaned_worktree: cleanup_worktree,
    })
}

pub async fn rebase_session_worktree(db: &StateStore, id: &str) -> Result<WorktreeRebaseOutcome> {
    let session = resolve_session(db, id)?;

    if matches!(
        session.state,
        SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale
    ) {
        anyhow::bail!(
            "Cannot rebase 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::rebase_onto_base(&worktree)?;

    Ok(WorktreeRebaseOutcome {
        session_id: session.id,
        branch: outcome.branch,
        base_branch: outcome.base_branch,
        already_up_to_date: outcome.already_up_to_date,
    })

View on GitHub (pinned to 8321021c54)