{"record":{"id":"37a3f183a3aa4d85","repo":"Hmbown/CodeWhale","slug":"exec-turn-ended-with-status-status-agent","errorCode":null,"errorMessage":"exec turn ended with status {status}","messagePattern":"exec turn ended with status (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/exec_agent.rs","lineNumber":1452,"sourceCode":"        // after all in-session retries are exhausted) from genuine task\n        // failures so supervisors and bench harnesses can tell them apart at\n        // the process level without parsing the stream. Genuine failures\n        // keep the historical `bail!` → exit 1 path.\n        let exit_code = exec_failure_exit_code(summary.error_category.as_deref());\n        if exit_code != 1 {\n            eprintln!(\"Error: exec turn failed: {error}\");\n            let _ = io::stdout().flush();\n            std::process::exit(exit_code);\n        }\n        bail!(\"exec turn failed: {error}\");\n    }\n\n    if matches!(\n        summary.status.as_deref(),\n        Some(\"failed\" | \"canceled\" | \"interrupted\")\n    ) {\n        let status = summary.status.as_deref().unwrap_or(\"unknown\");\n        bail!(\"exec turn ended with status {status}\");\n    }\n\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{ExecAgentEvents, exec_automation_services, exec_disallowed_tools};\n    use crate::core::engine::mock_engine_handle;\n    use crate::core::engine::tool_catalog::REQUEST_USER_INPUT_NAME;\n    use crate::core::events::{Event, TurnOutcomeStatus};\n    use crate::core::ops::{Op, SubAgentSettlement};\n    use codewhale_models::Usage;\n    use std::time::{Duration, Instant};\n\n    fn completed_parent(input_tokens: u32) -> Event {\n        let usage = Usage {\n            input_tokens,","sourceCodeStart":1434,"sourceCodeEnd":1470,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/exec_agent.rs#L1434-L1470","documentation":"After a CLI exec turn finishes, run_exec_agent checks the summary status; statuses of \"failed\", \"canceled\", or \"interrupted\" (or a missing status, reported as \"unknown\") are not successful completions, so the function bails with this error. It distinguishes a turn that ran but ended abnormally from one that threw an exception (error 893).","triggerScenarios":"Calling `codewhale exec` where the completed turn's summary reports status failed/canceled/interrupted — e.g. the model turn was cancelled by a signal, hit a failure classification, or the summary lacked a recognized status.","commonSituations":"User or orchestrator sent SIGINT/SIGTERM mid-turn; the turn hit the failure path recorded in the session summary; a bug or old session format produced a summary without a status string (shows as \"unknown\").","solutions":["Check the status word in the message: interrupted/canceled usually means a signal or cancellation — rerun without interrupting.","For \"failed\", inspect the session summary/logs for the failing step or tool output.","For \"unknown\", verify the session summary was written by a compatible Codewhale version and is not truncated.","Adjust the orchestrator to treat this exit as a turn-level failure and retry with backoff if appropriate."],"exampleFix":"// before\ncodewhale exec \"long task\" &   # killed by timeout => status interrupted\n// after\ntimeout 30m codewhale exec \"long task\" || echo \"turn ended with $?, inspect summary\"","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"let out = Command::new(\"codewhale\").args([\"exec\", prompt]).output()?;\nif !out.status.success() {\n    let msg = String::from_utf8_lossy(&out.stderr);\n    if msg.contains(\"ended with status interrupted\") || msg.contains(\"ended with status canceled\") {\n        // reschedule rather than treating as a hard failure\n    }\n}","preventionTips":["Protect long exec turns from SIGINT/SIGTERM in orchestrators, or handle resumption.","Use timeouts generous enough for the turn, and prefer explicit cancel APIs over signals.","Inspect the session summary status after each run and classify interrupted vs failed before retrying."],"tags":["exec","cli","turn-status","exit-code"],"backgroundTag":"invalid-state-transition","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"}