zeroclaw-labs/zeroclaw · error · anyhow::Error

no public catalog for family {family:?}

Error message

no public catalog for family {family:?}

What it means

The family is recognized in the catalog table, but it has no usable public catalog source: the models.dev lookup failed or returned empty, and the family has no OpenRouter vendor prefix fallback (table entries such as azure, bedrock, copilot, groq, lmstudio map to a models.dev key with None as the OpenRouter prefix, so there is no second source to try).

Source

Thrown at crates/zeroclaw-providers/src/catalog.rs:217

        return list_nearai_models().await;
    }
    if family == "atlascloud" {
        return list_atlascloud_models().await;
    }

    let Some((md_key, or_prefix)) = catalog_source_for(family) else {
        anyhow::bail!("unknown provider family {family:?}");
    };
    if let Some(k) = md_key
        && let Ok(ms) = crate::models_dev::list_models_for(k).await
        && !ms.is_empty()
    {
        return Ok(ms);
    }
    if let Some(p) = or_prefix {
        return crate::openrouter_catalog::list_models_for_vendor(p).await;
    }
    anyhow::bail!("no public catalog for family {family:?}")
}

#[must_use]
pub fn sort_model_catalog_for_chat(provider: &str, models: Vec<String>) -> Option<Vec<String>> {
    let provider_l = provider.to_ascii_lowercase();
    let mut ranked: Vec<(i32, String, String)> = models
        .into_iter()
        .filter_map(|model| {
            let model_l = model.to_ascii_lowercase();
            if is_non_chat_model_lower(&model_l) {
                None
            } else {
                Some((chat_model_rank_lower(&provider_l, &model_l), model_l, model))
            }
        })
        .collect();
    if ranked.is_empty() {
        return None;

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Retry once models.dev is reachable (verify with: curl -sS https://models.dev/api.json)
  2. Configure an explicit model list on the alias instead of relying on the live catalog
  3. Allow egress to models.dev in firewall or proxy rules
  4. Cache the catalog response at the application layer if you depend on it for startup
Defensive patterns

Strategy: fallback

Validate before calling

// Pre-check connectivity to the sole catalog source when the family
// has no OpenRouter fallback (prefix is None)
let (_, or_prefix) = zeroclaw_providers::catalog::catalog_source_for(family)
    .ok_or_else(|| anyhow::anyhow!("unknown family"))?;
if or_prefix.is_none() && !net_reachable("https://models.dev").await {
    return Ok(configured_static_models.to_vec());
}

Try / catch

match list_models_for_family("azure").await {
    Ok(models) => Ok(models),
    Err(e) if e.to_string().contains("no public catalog") => {
        Ok(static_model_list_from_config()) // degrade, do not fail the caller
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Calling list_models_for_family for e.g. "azure" or "copilot" while models.dev is unreachable, rate-limits the request, errors, or returns an empty list - the sole catalog source failed, so the call bails.

Common situations: Offline machine or firewall blocking models.dev; models.dev outage or temporary DNS failure; CI environments with restricted egress.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/3f68d12dea5a4da0. Report an issue: GitHub.