Hmbown/CodeWhale · error · anyhow::Error

The Codewhale service returned no connectable providers…

Error message

The Codewhale service returned no connectable providers. Check the account API origin, or try again

What it means

provider_catalog fetches the account's connectable providers, trims each row's id, and refuses to return an empty list. An empty catalog means the CLI cannot resolve any provider, so it throws with a hint to check the API origin or retry.

Solutions

  1. Verify the account API origin configuration points at the correct Codewhale service.
  2. Retry — the empty result may be transient.
  3. Check the account in the web console or via `codewhale account keys list` to confirm providers exist.
  4. Provision/connect a provider for the account if none exist.
Defensive patterns

Strategy: retry

Try / catch

// Rust
match cloud.provider_catalog() {
    Err(e) if e.to_string().contains("no connectable providers") => {
        // verify origin config, retry, or provision a provider
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling any provider-dependent cloud command when GET of the provider catalog returns zero rows — wrong origin, transient service error, or an account with no providers provisioned.

Common situations: Misconfigured account API origin (pointing at the wrong environment); brand-new account with no providers; service outage or degraded response.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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

Appendix: source

Thrown at crates/cli/src/cloud.rs:491

            method: HttpMethod::Get,
            path: "/api/model-providers".to_string(),
            bearer: None,
            body: None,
        })?;
        let listing: ProviderCatalogResponse = expect_json(response, &[200])?;
        let mut seen = std::collections::BTreeSet::new();
        let providers: Vec<CatalogProvider> = listing
            .providers
            .into_iter()
            .filter(|row| validate_provider_id(&row.id).is_ok())
            .filter(|row| seen.insert(row.id.trim().to_string()))
            .map(|mut row| {
                row.id = row.id.trim().to_string();
                row
            })
            .collect();
        if providers.is_empty() {
            bail!(
                "The Codewhale service returned no connectable providers. Check the account API origin, or try again"
            );
        }
        Ok(providers)
    }

    fn logout(&self) -> Result<bool> {
        let snapshot = self.account_store.snapshot()?;
        self.account_store
            .with_transaction(|transaction| -> Result<bool> {
                if !transaction.matches(&snapshot) {
                    bail!("The signed-in account changed. Refresh and try again.");
                }
                let stored = match transaction.load() {
                    Ok(Some(stored)) => stored,
                    Ok(None) | Err(_) => {
                        transaction.clear();
                        return Ok(false);

View on GitHub (pinned to 73e0f67d83)