jlcodes99/cockpit-tools · error
{} ({})
Error message
{} ({}) What it means
Generic process-teardown failure formatted as "{failure_message} ({pid_list})" in the shared close-and-verify routine of process_core_matching: after graceful close, close_pids, and a forced retry, collect_remaining_entries still finds processes matching the target dirs. The message names the failing operation and lists the PIDs that remain alive.
Source
Thrown at crates/cockpit-core/src/modules/process_core_matching.rs:3306
if let Err(err) = close_pids(&remaining_pids, 6) {
crate::modules::logger::log_warn(&format!(
"[{}] retry close_pids returned error: {}",
log_prefix, err
));
}
remaining_entries = collect_remaining_entries(&target_dirs);
}
}
if !remaining_entries.is_empty() {
let remaining_pids = collect_remaining_pids(&remaining_entries);
if let Some(detail_logger_fn) = detail_logger {
detail_logger_fn(&remaining_pids);
}
crate::modules::logger::log_error(&format!(
"[{}] still_running_entries={}",
log_prefix,
summarize_process_entries_for_log(&remaining_entries)
));
return Err(format!(
"{} ({})",
failure_message,
summarize_pid_list_for_log(&remaining_pids)
));
}
Ok(())
}
View on GitHub (pinned to 1ed8b77992)
Solutions
- Manually terminate the PIDs listed in parentheses in the message (kill -9 / Task Manager), then retry.
- Check whether a supervisor or auto-restart mechanism relaunches the processes; disable it before closing.
- Run with sufficient privileges (elevate) so signals can reach processes owned by other accounts.
- Increase the timeout or repeat the close once — the routine already retries force-kill with a 6s window.
- Inspect the '[<prefix>] still_running_entries=' log line to see which processes/dirs remained and why.
Example fix
// before: assuming close success
assert!(close_managed_instances_common().is_ok());
// after: parse remaining PIDs from the failure and escalate
match close_managed_instances_common() {
Err(msg) => {
let pids = extract_parenthesized_pids(&msg);
force_kill_elevated(&pids); // taskkill /F /PID ... or kill -9
}
Ok(_) => {}
} Defensive patterns
Strategy: try-catch
Validate before calling
// Before closing, verify no supervisor will respawn the targets
fn no_respawn_expected(match_cmdline: &str) -> bool {
!list_running_processes().iter().any(|p| {
p.cmdline.contains("supervisor") && p.cmdline.contains(match_cmdline)
})
} Type guard
fn parse_remaining_pids(err_msg: &str) -> Vec<u32> {
err_msg.rsplit_once('(').and_then(|(_, tail)| tail.trim_end_matches(')').split_whitespace().next())
.map(|s| s.split(',').filter_map(|p| p.trim().parse().ok()).collect())
.unwrap_or_default()
} Try / catch
match close_managed_instances() {
Err(msg) => {
let pids = parse_remaining_pids(&msg);
eprintln!("teardown failed, force-killing {:?}", pids);
force_kill_elevated(&pids); // taskkill /F or kill -9
}
Ok(_) => {}
} Prevention
- Disable auto-restart/supervisors for target instances before teardown.
- Run the close operation elevated when processes may belong to other users.
- Repeat the close once — the routine already does a 6s force-kill retry; a third pass may catch stragglers.
- Use the '[prefix] still_running_entries=' log line to find which directories' processes survived.
- Reboot if processes are stuck in uninterruptible wait and cannot be killed.
When it happens
Trigger: Calling any managed-instance close flow (Codex/Trae/opencode instances) when, even after two close_pids passes (graceful wait + 6s force retry), processes identified via target_dirs are still running — blocked signals, elevation mismatch, or respawned child processes.
Common situations: Supervisor/parent process respawning killed children; processes running under a different user; hung processes in uninterruptible wait; file locks held in the target dirs keeping processes alive; insufficient permissions without elevation.
Related errors
AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05).
Data as JSON: /api/errors/b43229c544e9d721.
Report an issue: GitHub.