{"record":{"id":"674a8d8fb4d3de65","repo":"BloopAI/vibe-kanban","slug":"failed-to-cleanly-kill-running-execution-processes-674a8d","errorCode":null,"errorMessage":"Failed to cleanly kill running execution processes","messagePattern":"Failed to cleanly kill running execution processes","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/server/src/startup.rs","lineNumber":191,"sourceCode":"    deployment\n        .track_if_analytics_allowed(\"session_start\", serde_json::json!({}))\n        .await;\n\n    // Preload global executor options cache for all executors with DEFAULT presets\n    tokio::spawn(async move {\n        executors::executors::utils::preload_global_executor_options_cache().await;\n    });\n\n    Ok(deployment)\n}\n\n/// Gracefully shut down running execution processes.\npub async fn perform_cleanup_actions(deployment: &DeploymentImpl) {\n    deployment\n        .container()\n        .kill_all_running_processes()\n        .await\n        .expect(\"Failed to cleanly kill running execution processes\");\n}\n\nconst LEGACY_ATTACHMENT_MIGRATION_MARKER: &str = \".attachment-directories-migrated-v1\";\n\n#[derive(Default)]\nstruct DirectoryMigrationStats {\n    moved_files: u64,\n    removed_duplicates: u64,\n    created_directories: u64,\n    failures: u64,\n}\n\nimpl DirectoryMigrationStats {\n    fn merge(&mut self, other: DirectoryMigrationStats) {\n        self.moved_files += other.moved_files;\n        self.removed_duplicates += other.removed_duplicates;\n        self.created_directories += other.created_directories;\n        self.failures += other.failures;","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/server/src/startup.rs#L173-L209","documentation":"When the server shuts down gracefully, `perform_cleanup_actions` kills all execution processes tracked by the container service. `kill_all_running_processes()` returns a Result and the `.expect(...)` panics if any kill fails. The comment's promise of a 'graceful' shutdown is enforced here: any lingering execution that cannot be terminated crashes the cleanup path.","triggerScenarios":"Calling `serve()`'s shutdown path (or `perform_cleanup_actions` directly) while `container().kill_all_running_processes()` returns an Err — e.g. the underlying executor/process handles are stale, the process already exited with an unexpected state, or an internal error occurs while enumerating/killing tracked executions.","commonSituations":"Killing the app during an active task execution where child processes have already re-parented or become zombies; container/executors on remote deployments returning errors mid-kill; shutdown racing with an execution that just finished, producing a stale-handle error.","solutions":["Inspect the underlying error from kill_all_running_processes to see which execution/process failed and why","Retrying the kill or sending SIGKILL after a graceful-signal timeout usually clears lingering processes","Treat kill failures as non-fatal at shutdown: log the error instead of panicking, since the process is exiting anyway","Ensure executors track process handles (Child::id etc.) and reap exited children so kills target live PIDs","Add a cleanup timeout so a stuck kill cannot hang shutdown"],"exampleFix":"// before\ndeployment.container().kill_all_running_processes().await\n    .expect(\"Failed to cleanly kill running execution processes\");\n// after\nif let Err(e) = deployment.container().kill_all_running_processes().await {\n    tracing::error!(\"Failed to kill running execution processes during shutdown: {}\", e);\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Catch the cleanup panic at the shutdown boundary:\nlet handle = tokio::spawn(async move { perform_cleanup_actions(&deployment).await });\nif let Err(join_err) = handle.await {\n    tracing::error!(\"cleanup panicked: {}\", join_err); // don't crash shutdown\n}\n// Preferred: replace expect with logged error inside perform_cleanup_actions","preventionTips":["Wrap kill_all_running_processes in error logging rather than expect at shutdown","Add a grace period then SIGKILL fallback for stubborn processes","Reap finished child processes so kill targets are always live handles","Test shutdown while executions are actively running","Keep executor process registries free of stale entries"],"tags":["shutdown","process-kill","panic","cleanup"],"backgroundTag":"process-kill-failed","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}