Hmbown/CodeWhale · error · anyhow::Error
Cloud agents are not available for this account yet; cloud…
Error message
Cloud agents are not available for this account yet; cloud dispatch fails closed (no sandbox, no push, no PR).
What it means
api_key() found no stored cloud API key, so the launcher returns the fail-closed message: cloud dispatch is refused entirely because cloud sandboxes act under your account and would otherwise have no sandbox, push, or PR capability. This is an intentional guard, not a transient fault.
Solutions
- Set CODEWHALE_API_KEY to a `cwc_key_…` machine key (Account → API keys in the web app)
- Complete the cloud onboarding/linking flow in the app
- Verify the key is readable by the process (env, config file, keychain)
- Re-confirm cloud dispatch after credentials are in place
Example fix
// before # no key // after export CODEWHALE_API_KEY=cwc_key_xxxxxxxxxxxx
Defensive patterns
Strategy: validation
Validate before calling
if std::env::var("CODEWHALE_API_KEY").map_or(true, |k| !k.starts_with("cwc_key_")) {
eprintln!("Set CODEWHALE_API_KEY (Account → API keys) before cloud dispatch");
} Type guard
fn has_cloud_api_key() -> bool {
std::env::var("CODEWHALE_API_KEY").map_or(false, |k| k.starts_with("cwc_key_"))
} Try / catch
match launcher.create_sandbox(&job) {
Err(e) if e.to_string().contains("not available for this account") => {
prompt_user_to_link_account();
}
other => other?,
} Prevention
- Configure the machine key during onboarding
- Check credential presence before offering cloud features
- Do not clear keychain/config entries silently
- Surface the fail-closed reason in the UI
When it happens
Trigger: Any DaytonaLauncher operation (e.g. create_sandbox) calling Self::api_key() when read_api_key() returns None (crates/tui/src/cloud_dispatch.rs:1409).
Common situations: Fresh installs without cloud setup, users who never linked a Codewhale account, or credentials cleared from config/keychain.
Understand the failure class
Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.
Related errors
- Cloud agents are not available for this account yet; cloud…
- cloud dispatch fails closed: the cloud agent runs Codewhale…
- API key not found. Run 'codewhale auth set --provider '…
- DeepSeek API key not found. 1. Get a key: …
- external credential access for
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/5eee9d1b8218ddee.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/cloud_dispatch.rs:1409
crate::tls::reqwest_blocking_client_builder()
.connect_timeout(std::time::Duration::from_secs(8))
.redirect(reqwest::redirect::Policy::none())
.build()
.map_err(|error| error.to_string())
})
.clone()
.map_err(|message| anyhow!("failed to initialize the cloud agent client: {message}"))
}
/// The total-timeout budget for a harness-carrying client, in seconds.
/// Public to the crate so the runner's tests can pin it against the
/// declared `HARNESS_TIMEOUT_SECS`.
pub(crate) fn harness_client_budget_secs(command: &HarnessCommand) -> u64 {
u64::from(command.timeout_secs).saturating_add(Self::HARNESS_CLIENT_SLACK_SECS)
}
fn api_key() -> Result<String> {
read_api_key().ok_or_else(|| anyhow!(missing_credentials_message()))
}
/// Control-plane URL under the validated base.
fn control_plane_url(path: &str) -> Result<reqwest::Url> {
let base = validate_outbound_origin(&daytona_api_url())?;
join_api_path(base, path).context("failed to build the cloud agent request URL")
}
/// Toolbox base for one sandbox: `{toolboxProxyUrl}/{sandboxId}`.
fn toolbox_base(receipt: &SandboxReceipt) -> Result<reqwest::Url> {
if !valid_sandbox_id(&receipt.sandbox_id) {
bail!("the sandbox id is not a usable path token");
}
let fallback = format!("{}/toolbox", DEFAULT_DAYTONA_API);
let raw = receipt.toolbox_url.as_deref().unwrap_or(&fallback);
let base = validate_outbound_origin(raw)?;
join_api_path(base, &receipt.sandbox_id).context("failed to build the sandbox toolbox URL")
}View on GitHub (pinned to 73e0f67d83)