Hmbown/CodeWhale · error

exec turn failed

Error message

exec turn failed: {error}

What it means

When a CLI exec turn fails with an error category that maps to a non-1 exit code, run_exec_agent prints the failure to stderr and exits the process directly with that code; for the category that maps to exit code 1 it instead returns this anyhow error from the function. Either way the message surfaces the underlying turn error to the caller of the exec entrypoint.

Solutions

  1. Read the `{error}` text in the message/preceding stderr output to identify the underlying turn failure and fix that cause.
  2. For provider/API errors, verify the configured route (provider, model, API key) is valid and reachable.
  3. Retry the exec command if the failure was transient; non-1 exit codes are returned as process exit codes for that purpose.
  4. Inspect summary.error_category to map the failure to its documented exit code and handling in your script.

Example fix

// before (scripting blindly)
codewhale exec "prompt"
// after
codewhale exec "prompt" || { echo "exec failed: $?"; retry_or_alert; }
Defensive patterns

Strategy: try-catch

Try / catch

match codewhale_exec_status {
    0 => {}, // success
    code @ 2.. => { eprintln!("exec failed with categorized exit {code}; see stderr"); }
    _ => { eprintln!("exec turn failed (exit 1): inspect the error text"); }
}

Prevention

When it happens

Trigger: A `codewhale exec` turn fails (provider error, tool failure, aborted turn) and `exec_failure_exit_code(summary.error_category)` yields 1 — the error is propagated as `bail!("exec turn failed: {error}")`.

Common situations: Transient upstream/API errors during scripted exec runs; a misconfigured provider route in headless/CI usage; the prompt triggered a tool that failed and the turn aborted with a generic error category.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/d9b0470726d17a06. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/exec_agent.rs:1444

    if json_output {
        println!("{}", serde_json::to_string_pretty(&summary)?);
    }

    if let Some(error) = summary.error.as_ref()
        && !error.trim().is_empty()
    {
        // Distinguish retryable infrastructure failures (provider/transport,
        // after all in-session retries are exhausted) from genuine task
        // failures so supervisors and bench harnesses can tell them apart at
        // the process level without parsing the stream. Genuine failures
        // keep the historical `bail!` → exit 1 path.
        let exit_code = exec_failure_exit_code(summary.error_category.as_deref());
        if exit_code != 1 {
            eprintln!("Error: exec turn failed: {error}");
            let _ = io::stdout().flush();
            std::process::exit(exit_code);
        }
        bail!("exec turn failed: {error}");
    }

    if matches!(
        summary.status.as_deref(),
        Some("failed" | "canceled" | "interrupted")
    ) {
        let status = summary.status.as_deref().unwrap_or("unknown");
        bail!("exec turn ended with status {status}");
    }

    Ok(())
}

#[cfg(test)]
mod tests {
    use super::{ExecAgentEvents, exec_automation_services, exec_disallowed_tools};
    use crate::core::engine::mock_engine_handle;
    use crate::core::engine::tool_catalog::REQUEST_USER_INPUT_NAME;

View on GitHub (pinned to 73e0f67d83)