{"record":{"id":"4cb6d858874ac809","repo":"Hmbown/CodeWhale","slug":"codewhale-runtime-thread-panicked-message","errorCode":null,"errorMessage":"Codewhale runtime thread panicked: {message}","messagePattern":"Codewhale runtime thread panicked: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/tui/src/lib.rs","lineNumber":1884,"sourceCode":"    // on the ubuntu CI leg). The fat frames are the debug poll functions of\n    // the giant top-level futures (`run_async_main_inner` ~5.5 MiB, `run_tui`\n    // ~3.2 MiB, `handle_view_events` ~2.1 MiB), so any small addition to them\n    // re-tips a zero-margin stack. 32 MiB restores real headroom; the cost is\n    // address space only, since thread stacks commit lazily.\n    let runtime_thread = std::thread::Builder::new()\n        .name(\"codewhale-main\".to_string())\n        .stack_size(CODEWHALE_MAIN_STACK_BYTES)\n        .spawn(move || run_async_main(cli, command, plugin_discovery, plugin_registry))\n        .context(\"Failed to start the Codewhale runtime thread\")?;\n    match runtime_thread.join() {\n        Ok(result) => result,\n        Err(payload) => {\n            let message = payload\n                .downcast_ref::<&str>()\n                .map(|value| (*value).to_string())\n                .or_else(|| payload.downcast_ref::<String>().cloned())\n                .unwrap_or_else(|| \"unknown panic payload\".to_string());\n            Err(anyhow!(\"Codewhale runtime thread panicked: {message}\"))\n        }\n    }\n}\n\nfn run_async_main(\n    cli: Cli,\n    command: Option<Commands>,\n    plugin_discovery: Arc<crate::plugins::PluginDiscoveryContext>,\n    plugin_registry: Arc<crate::plugins::PluginRegistry>,\n) -> Result<()> {\n    build_runtime(command.as_ref())?.block_on(run_async_main_inner(\n        cli,\n        command,\n        plugin_discovery,\n        plugin_registry,\n    ))\n}\n","sourceCodeStart":1866,"sourceCodeEnd":1902,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/lib.rs#L1866-L1902","documentation":"The CLI runs Codewhale work on a dedicated runtime thread and joins it. If that thread panics, the panic payload (`&str` or `String`, else \"unknown panic payload\") is re-caught and rethrown as this anyhow error on the main thread, preserving the panic message for the user.","triggerScenarios":"Any panic (`panic!`, unwrapped `None`/`Err`, index out of bounds, assertion) inside code executing on the Codewhale runtime thread.","commonSituations":"A bug in a provider integration or tool handler panics while the TUI is running; the user sees this wrapper message instead of an abort.","solutions":["Read the `{message}` suffix to identify the actual panic and fix the underlying bug at that site.","Reproduce with the same input/provider and add a graceful error return instead of a panic path.","Check for known panicking calls (unwrap/expect) in the module named by the panic message."],"exampleFix":"// before\nlet cfg = config.expect(\"config must exist\");\n// after\nlet cfg = config.ok_or_else(|| anyhow!(\"configuration missing\"))?;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match run_on_runtime_thread(...) {\n    Err(e) if e.to_string().starts_with(\"Codewhale runtime thread panicked\") => {\n        eprintln!(\"runtime crashed: {e:#}\"); // then fix the panic site named in the message\n    }\n    other => other?,\n}","preventionTips":["Replace `unwrap`/`expect` in runtime-thread code with anyhow error returns.","Run `cargo test --workspace` and fuzz risky input paths to surface panics before release.","Always log the full panic message; it names the failing module."],"tags":["panic","runtime","thread"],"backgroundTag":"internal-invariant-violation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}