affaan-m/ECC · error · anyhow::Error
Cannot delete active session {} while it is {}
Error message
Cannot delete active session {} while it is {} What it means
The delete_session function refuses to delete a session in an active state (Pending, Running, or Idle). Deleting an active session would orphan a running agent process and leave resources dangling. Notably, Stale sessions are NOT blocked — stale sessions can be deleted because the heartbeat has expired, suggesting the process is likely dead.
Source
Thrown at ecc2/src/session/manager.rs:2314
dirty.push(entry.session_id.clone());
} else if entry.worktree_health == worktree::WorktreeHealth::Conflicted {
conflicted.push(entry.session_id.clone());
} else {
queue_blocked.push(entry.session_id.clone());
}
}
(active, conflicted, dirty, queue_blocked)
}
pub async fn delete_session(db: &StateStore, id: &str) -> Result<()> {
let session = resolve_session(db, id)?;
if matches!(
session.state,
SessionState::Pending | SessionState::Running | SessionState::Idle
) {
anyhow::bail!(
"Cannot delete active session {} while it is {}",
session.id,
session.state
);
}
if let Some(worktree) = session.worktree.as_ref() {
let _ = crate::worktree::remove(worktree);
}
db.delete_session(&session.id)?;
Ok(())
}
fn agent_program(cfg: &Config, agent_type: &str) -> Result<PathBuf> {
let harness = HarnessKind::from_agent_type(agent_type);
let runner_key = SessionHarnessInfo::runner_key(agent_type);
if let Some(runner) = cfg.harness_runner(&runner_key) {View on GitHub (pinned to 01e15490f0)
Solutions
- Call stop_session first to transition the session to a terminal state, then delete
- Check that session.state is not Pending, Running, or Idle before calling delete_session
- For stuck sessions, force-stop or mark as failed before deletion
- Stale sessions can be deleted directly — wait for the heartbeat to expire if the process is unresponsive
Example fix
// before
delete_session(db, &id).await?;
// after
let session = resolve_session(db, &id)?;
if matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle) {
stop_session(db, &id).await?;
}
delete_session(db, &id).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) {
stop_session(db, id).await?;
} Type guard
fn is_deletable(session: &Session) -> bool {
!matches!(
session.state,
SessionState::Pending | SessionState::Running | SessionState::Idle
)
} Prevention
- Always call stop_session before delete_session in automated cleanup scripts
- Note that Stale sessions CAN be deleted — wait for heartbeat expiry before deleting stuck sessions
- Expose delete only for non-active sessions in the UI
When it happens
Trigger: Calling delete_session(db, id) for a session in SessionState::Pending, Running, or Idle. (Stale sessions are allowed to be deleted.)
Common situations: User deletes a session that is still running or pending. Automated cleanup script that does not check state. Session appears hung but is technically in Idle state between operations.
Related errors
- Completed sessions cannot be resumed: {}
- Session is already running: {}
- Cannot merge active session {} while it is {}
- Cannot rebase active session {} while it is {}
- Work item ${target.id} is already done; cannot claim.
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/de97b9cfd61fc0ac.
Report an issue: GitHub.