{"record":{"id":"b17a1609fa1f4336","repo":"Hmbown/CodeWhale","slug":"shell-tracking-hit-an-internal-error-restart-cod","errorCode":null,"errorMessage":"Shell tracking hit an internal error — restart Codewhale to recover.","messagePattern":"Shell tracking hit an internal error — restart Codewhale to recover\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/ui.rs","lineNumber":3079,"sourceCode":"\n    match request_active_foreground_shell_background(app) {\n        Ok(()) => {\n            app.status_message = Some(\"Moving current shell command to /jobs...\".to_string());\n        }\n        Err(err) => {\n            app.status_message = Some(err.to_string());\n        }\n    }\n}\n\nfn request_active_foreground_shell_background(app: &App) -> Result<()> {\n    let shell_manager = app\n        .runtime_services\n        .shell_manager\n        .clone()\n        .context(\"No shell session is active.\")?;\n    let mut manager = shell_manager.lock().map_err(|_| {\n        anyhow::anyhow!(\"Shell tracking hit an internal error — restart Codewhale to recover.\")\n    })?;\n    manager.request_foreground_background();\n    Ok(())\n}\n\npub(crate) fn prefill_jobs_cancel_all_if_tasks_sidebar(app: &mut App) -> bool {\n    if !app.view_stack.is_empty()\n        || app.work_surface.panel != crate::tui::work_surface::RailPanel::Tasks\n        || app.work_surface.last_area.is_none()\n        || !app\n            .task_panel\n            .iter()\n            .any(|task| task.id.starts_with(\"shell_\") && task.status == \"running\")\n    {\n        return false;\n    }\n\n    app.input = \"/jobs cancel-all\".to_string();","sourceCodeStart":3061,"sourceCodeEnd":3097,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tui/ui.rs#L3061-L3097","documentation":"The shell-session manager's Mutex is poisoned: some thread panicked while holding the lock, so every later .lock() returns Err and shell tracking is dead in this process. Rust poisons a mutex whenever a panic unwinds through a critical section, and request_active_foreground_shell_background maps that poisoning to this message telling the user to restart, because poisoned state is not recoverable through this path.","triggerScenarios":"Calling request_active_foreground_shell_background() (backgrounding the foreground shell) after any earlier panic anywhere the shell_manager lock was held - e.g. a PTY I/O thread or command-tracking code path panicked and unwound through the locked region.","commonSituations":"A bug-triggering panic during shell output handling in an older build; stress scenarios killing worker threads; unwinding across lock boundaries.","solutions":["Restart the TUI as the message instructs - the poisoned lock cannot be recovered in-process","Update to a newer build; the root cause is the original panic, so check the changelog/issue tracker for a fix","Capture logs and the panic backtrace (RUST_BACKTRACE=1) and report it","Avoid the interaction that triggered the original panic until the fix is installed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match shell_manager.lock() {\n    Ok(mut manager) => { manager.request_foreground_background(); Ok(()) }\n    Err(poisoned) => {\n        tracing::error!(\"shell manager lock poisoned: {:?}\", poisoned);\n        // only if invariants are known re-establishable:\n        // let mut manager = poisoned.into_inner();\n        disable_shell_tracking_and_prompt_restart()\n    }\n}","preventionTips":["Never panic while holding a shared mutex - validate inputs before locking","Catch and log panics at thread boundaries so one bug does not poison shared state","Consider lock poisoning recovery (into_inner) only when state invariants are re-verifiable"],"tags":["mutex","poisoned-lock","panic","shell","concurrency"],"backgroundTag":"mutex-poisoned","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}