{"record":{"id":"27d2444cfac74f6a","repo":"NousResearch/hermes-agent","slug":"hermes-is-still-running-close-all-hermes-windows","errorCode":null,"errorMessage":"Hermes is still running. Close all Hermes windows and try the update again.","messagePattern":"Hermes is still running\\. Close all Hermes windows and try the update again\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"apps/bootstrap-installer/src-tauri/src/update.rs","lineNumber":454,"sourceCode":"        Some(code) if code == UPDATE_EXIT_CONCURRENT => {\n            let msg = \"Hermes is still running. Close all Hermes windows and try \\\n                       the update again.\"\n                .to_string();\n            emit_stage(\n                &app,\n                \"update\",\n                StageState::Failed,\n                Some(update_ms),\n                Some(msg.clone()),\n            );\n            emit(\n                &app,\n                BootstrapEvent::Failed {\n                    stage: Some(\"update\".into()),\n                    error: msg.clone(),\n                },\n            );\n            return Err(anyhow!(msg));\n        }\n        other => {\n            let msg = format!(\n                \"hermes update failed (exit {:?}). See {} for details.\",\n                other,\n                crate::paths::hermes_home()\n                    .join(\"logs\")\n                    .join(\"update.log\")\n                    .display()\n            );\n            emit_stage(\n                &app,\n                \"update\",\n                StageState::Failed,\n                Some(update_ms),\n                Some(msg.clone()),\n            );\n            emit(","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/bootstrap-installer/src-tauri/src/update.rs#L436-L472","documentation":"Stage-2 outcome of the update flow: `hermes update` exited with a status that maps to the 'still running' arm — the CLI refused because Hermes processes were detected alive. Before overwriting files the updater must have the old desktop app (and any Hermes sessions) shut down; the emitted stage 'update' is marked Failed with this message.","triggerScenarios":"Running the updater while Hermes desktop windows, a dashboard tab backend, TUI sessions, or gateway processes are still alive; the stage-1 'wait for the old desktop to die' step timed out or raced a slow shutdown; a background hermes process (cron ticker, serve backend) survived the window close.","commonSituations":"User clicked update but left a dashboard tab open in a browser; an Electron main process took seconds to exit and the update started meanwhile; a stray `hermes serve` or gateway process from an earlier session is still running.","solutions":["Close all Hermes windows, tabs, and terminals running hermes, then retry the update.","Check for lingering processes (`ps aux | grep -i hermes` / Task Manager) and end them.","Retry — shutdown races are timing-dependent and usually succeed on a second attempt once processes are gone."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight: no hermes processes should be alive before updating.\nfn hermes_running() -> bool {\n    let out = if cfg!(target_os = \"windows\") {\n        std::process::Command::new(\"tasklist\").args([\"/FI\", \"IMAGENAME eq hermes.exe\"]).output()\n    } else {\n        std::process::Command::new(\"pgrep\").args([\"-f\", \"hermes\"]).output()\n    };\n    out.map(|o| !o.stdout.is_empty()).unwrap_or(true) // fail closed\n}\n\nif hermes_running() {\n    eprintln!(\"Close all Hermes windows/processes before updating.\");\n}","typeGuard":null,"tryCatchPattern":"// Treat as retryable, not fatal: prompt the user and retry the update once processes are gone.\nmatch exit {\n    ExitCode::STILL_RUNNING => {\n        emit_stage(&app, \"update\", StageState::Failed, Some(ms), Some(\"Hermes is still running\".into()));\n        // surface a retry affordance in the UI rather than a dead end\n    }\n    _ => { /* real failure: consult update.log */ }\n}","preventionTips":["Close all Hermes windows, tabs, and terminal sessions before triggering the update.","Have the updater wait longer / poll for process exit before declaring the race lost.","Make dashboards that spawn updates shut their backend down first."],"tags":["update","process-lifecycle","bootstrap-installer"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}