affaan-m/ECC · error · anyhow::Error
Cannot merge active session {} while it is {}
Error message
Cannot merge active session {} while it is {} What it means
The merge_session_worktree function refuses to merge a session whose state is still active (Pending, Running, Idle, or Stale). Merging an active session's worktree could corrupt in-flight work since the agent process may still be writing files. The session must reach a terminal state (Completed, Failed, Cancelled) before merging is safe.
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 01e15490f0)
Solutions
- Stop or complete the session before calling merge_session_worktree
- Check session state is terminal (Completed, Failed, or Cancelled) before attempting merge
- For stale sessions, run the stale-session cleanup or mark them failed before merging
- Wire the merge call to a post-completion hook so it only fires after the agent exits
Example fix
// before
merge_session_worktree(db, &id, true).await?;
// after
let session = resolve_session(db, &id)?;
if matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale) {
return Err(anyhow!("Stop session {} before merging (current state: {})", id, session.state));
}
merge_session_worktree(db, &id, true).await?; Defensive patterns
Strategy: type-guard
Validate before calling
let session = resolve_session(db, id)?;
if matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale) {
return Err(anyhow!("Stop session {} (state: {}) before merging", id, session.state));
} Type guard
fn is_mergeable(session: &Session) -> bool {
!matches!(
session.state,
SessionState::Pending | SessionState::Running | SessionState::Idle | SessionState::Stale
)
} Prevention
- Only expose merge actions in the UI for sessions in terminal states
- Call stop_session before merge in automated workflows
- For stale sessions, run stale cleanup to transition them to a terminal state first
When it happens
Trigger: Calling merge_session_worktree(db, id, cleanup) for a session in SessionState::Pending, Running, Idle, or Stale.
Common situations: User clicks 'merge' on a session that hasn't finished. Session appears idle but is between tool calls. Stale sessions (heartbeat expired) are still considered active for merge safety.
Related errors
- Cannot rebase active session {} while it is {}
- Completed sessions cannot be resumed: {}
- Session is already running: {}
- Session {} has no attached worktree
- Cannot delete active session {} while it is {}
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/9102631c77e66c13.
Report an issue: GitHub.