{"record":{"id":"de97b9cfd61fc0ac","repo":"affaan-m/ECC","slug":"cannot-delete-active-session-while-it-is","errorCode":null,"errorMessage":"Cannot delete active session {} while it is {}","messagePattern":"Cannot delete active session (.+?) while it is (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"ecc2/src/session/manager.rs","lineNumber":2314,"sourceCode":"            dirty.push(entry.session_id.clone());\n        } else if entry.worktree_health == worktree::WorktreeHealth::Conflicted {\n            conflicted.push(entry.session_id.clone());\n        } else {\n            queue_blocked.push(entry.session_id.clone());\n        }\n    }\n\n    (active, conflicted, dirty, queue_blocked)\n}\n\npub async fn delete_session(db: &StateStore, id: &str) -> Result<()> {\n    let session = resolve_session(db, id)?;\n\n    if matches!(\n        session.state,\n        SessionState::Pending | SessionState::Running | SessionState::Idle\n    ) {\n        anyhow::bail!(\n            \"Cannot delete active session {} while it is {}\",\n            session.id,\n            session.state\n        );\n    }\n\n    if let Some(worktree) = session.worktree.as_ref() {\n        let _ = crate::worktree::remove(worktree);\n    }\n\n    db.delete_session(&session.id)?;\n    Ok(())\n}\n\nfn agent_program(cfg: &Config, agent_type: &str) -> Result<PathBuf> {\n    let harness = HarnessKind::from_agent_type(agent_type);\n    let runner_key = SessionHarnessInfo::runner_key(agent_type);\n    if let Some(runner) = cfg.harness_runner(&runner_key) {","sourceCodeStart":2296,"sourceCodeEnd":2332,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/ecc2/src/session/manager.rs#L2296-L2332","documentation":"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.","triggerScenarios":"Calling delete_session(db, id) for a session in SessionState::Pending, Running, or Idle. (Stale sessions are allowed to be deleted.)","commonSituations":"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.","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"],"exampleFix":"// before\ndelete_session(db, &id).await?;\n\n// after\nlet session = resolve_session(db, &id)?;\nif matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle) {\n    stop_session(db, &id).await?;\n}\ndelete_session(db, &id).await?;","handlingStrategy":"type-guard","validationCode":"let session = resolve_session(db, id)?;\nif matches!(session.state, SessionState::Pending | SessionState::Running | SessionState::Idle) {\n    stop_session(db, id).await?;\n}","typeGuard":"fn is_deletable(session: &Session) -> bool {\n    !matches!(\n        session.state,\n        SessionState::Pending | SessionState::Running | SessionState::Idle\n    )\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["sessions","lifecycle","delete","state-machine"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}