{"record":{"id":"0fe1ee7c1525cbcb","repo":"affaan-m/ECC","slug":"session-is-already-running","errorCode":null,"errorMessage":"Session is already running: {}","messagePattern":"Session is already running: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"ecc2/src/session/manager.rs","lineNumber":1520,"sourceCode":"\npub async fn resume_session(db: &StateStore, cfg: &Config, id: &str) -> Result<String> {\n    resume_session_with_program(db, cfg, id, None).await\n}\n\nasync fn resume_session_with_program(\n    db: &StateStore,\n    _cfg: &Config,\n    id: &str,\n    runner_executable_override: Option<&Path>,\n) -> Result<String> {\n    let session = resolve_session(db, id)?;\n\n    if session.state == SessionState::Completed {\n        anyhow::bail!(\"Completed sessions cannot be resumed: {}\", session.id);\n    }\n\n    if session.state == SessionState::Running {\n        anyhow::bail!(\"Session is already running: {}\", session.id);\n    }\n\n    db.update_state_and_pid(&session.id, &SessionState::Pending, None)?;\n    if let Some(worktree) = session.worktree.as_ref() {\n        if let Err(error) = worktree::sync_shared_dependency_dirs(worktree) {\n            tracing::warn!(\n                \"Shared dependency cache sync warning for resumed session {}: {error}\",\n                session.id\n            );\n        }\n    }\n    let runner_executable = match runner_executable_override {\n        Some(program) => program.to_path_buf(),\n        None => std::env::current_exe().context(\"Failed to resolve ECC executable path\")?,\n    };\n    spawn_session_runner_for_program(\n        &session.task,\n        &session.id,","sourceCodeStart":1502,"sourceCodeEnd":1538,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/ecc2/src/session/manager.rs#L1502-L1538","documentation":"resume_session_with_program refuses to resume a session that is already in the Running state, since resuming would start a second concurrent execution of the same session. The guard prevents duplicate processes and pid/state corruption.","triggerScenarios":"Calling resume_session(id) (or via resume_session_requeues_failed_session) while the session's stored state is SessionState::Running.","commonSituations":"Double-clicking a resume button; a scheduler re-triggering resume while the first process is still alive; a crashed process left the pid registered and the state Running; concurrent automation workers both trying to resume the same session.","solutions":["Check the session state and skip if already Running","Wait for the running session to finish before resuming","If the state is stuck as Running due to a crash, reset state (update_state_and_pid) after verifying no live process holds the pid","Serialize resume calls with a lock so only one worker resumes a given session"],"exampleFix":"// before\nresume_session(db, id)?;\n// after\nlet session = resolve_session(db, id)?;\nif session.state != SessionState::Running {\n    resume_session(db, id)?;\n} else {\n    eprintln!(\"session {} already running; skipping\", id);\n}","handlingStrategy":"validation","validationCode":"let session = resolve_session(db, id)?;\nif session.state == SessionState::Running {\n    return Err(format!(\"session {} is already running\", id));\n}","typeGuard":"fn is_stopped(s: &Session) -> bool { !matches!(s.state, SessionState::Running) }","tryCatchPattern":"match resume_session(db, id) {\n    Err(e) if e.to_string().contains(\"already running\") => { /* poll until finished or skip */ }\n    other => other?,\n}","preventionTips":["Use a lock/claim so only one worker resumes a session at a time","Detect crashed runners and reset stale Running states via update_state_and_pid","Debounce resume triggers in UIs"],"tags":["session","state-machine","concurrency","resume"],"backgroundTag":"invalid-state-transition","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}