{"record":{"id":"5eee9d1b8218ddee","repo":"Hmbown/CodeWhale","slug":"cloud-agents-are-not-available-for-this-account-yet-cloud-5eee9d","errorCode":null,"errorMessage":"Cloud agents are not available for this account yet; cloud dispatch fails closed (no sandbox, no push, no PR).","messagePattern":"Cloud agents are not available for this account yet; cloud dispatch fails closed \\(no sandbox, no push, no PR\\)\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/cloud_dispatch.rs","lineNumber":1409,"sourceCode":"                crate::tls::reqwest_blocking_client_builder()\n                    .connect_timeout(std::time::Duration::from_secs(8))\n                    .redirect(reqwest::redirect::Policy::none())\n                    .build()\n                    .map_err(|error| error.to_string())\n            })\n            .clone()\n            .map_err(|message| anyhow!(\"failed to initialize the cloud agent client: {message}\"))\n    }\n\n    /// The total-timeout budget for a harness-carrying client, in seconds.\n    /// Public to the crate so the runner's tests can pin it against the\n    /// declared `HARNESS_TIMEOUT_SECS`.\n    pub(crate) fn harness_client_budget_secs(command: &HarnessCommand) -> u64 {\n        u64::from(command.timeout_secs).saturating_add(Self::HARNESS_CLIENT_SLACK_SECS)\n    }\n\n    fn api_key() -> Result<String> {\n        read_api_key().ok_or_else(|| anyhow!(missing_credentials_message()))\n    }\n\n    /// Control-plane URL under the validated base.\n    fn control_plane_url(path: &str) -> Result<reqwest::Url> {\n        let base = validate_outbound_origin(&daytona_api_url())?;\n        join_api_path(base, path).context(\"failed to build the cloud agent request URL\")\n    }\n\n    /// Toolbox base for one sandbox: `{toolboxProxyUrl}/{sandboxId}`.\n    fn toolbox_base(receipt: &SandboxReceipt) -> Result<reqwest::Url> {\n        if !valid_sandbox_id(&receipt.sandbox_id) {\n            bail!(\"the sandbox id is not a usable path token\");\n        }\n        let fallback = format!(\"{}/toolbox\", DEFAULT_DAYTONA_API);\n        let raw = receipt.toolbox_url.as_deref().unwrap_or(&fallback);\n        let base = validate_outbound_origin(raw)?;\n        join_api_path(base, &receipt.sandbox_id).context(\"failed to build the sandbox toolbox URL\")\n    }","sourceCodeStart":1391,"sourceCodeEnd":1427,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/cloud_dispatch.rs#L1391-L1427","documentation":"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.","triggerScenarios":"Any DaytonaLauncher operation (e.g. create_sandbox) calling Self::api_key() when read_api_key() returns None (crates/tui/src/cloud_dispatch.rs:1409).","commonSituations":"Fresh installs without cloud setup, users who never linked a Codewhale account, or credentials cleared from config/keychain.","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"],"exampleFix":"// before\n# no key\n// after\nexport CODEWHALE_API_KEY=cwc_key_xxxxxxxxxxxx","handlingStrategy":"validation","validationCode":"if std::env::var(\"CODEWHALE_API_KEY\").map_or(true, |k| !k.starts_with(\"cwc_key_\")) {\n    eprintln!(\"Set CODEWHALE_API_KEY (Account → API keys) before cloud dispatch\");\n}","typeGuard":"fn has_cloud_api_key() -> bool {\n    std::env::var(\"CODEWHALE_API_KEY\").map_or(false, |k| k.starts_with(\"cwc_key_\"))\n}","tryCatchPattern":"match launcher.create_sandbox(&job) {\n    Err(e) if e.to_string().contains(\"not available for this account\") => {\n        prompt_user_to_link_account();\n    }\n    other => other?,\n}","preventionTips":["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"],"tags":["auth","cloud","credentials"],"backgroundTag":"missing-api-key","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}