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
- Retry once models.dev is reachable (verify with: curl -sS https://models.dev/api.json)
- Configure an explicit model list on the alias instead of relying on the live catalog
- Allow egress to models.dev in firewall or proxy rules
- 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
- Always configure a static model fallback list for families whose only catalog is models.dev
- Cache the last successful catalog result and reuse it on network failure
- Allow egress to models.dev in CI and container network policies
- Do not treat model listing as mandatory for chat - degrade gracefully
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
- exceeded {} reconnect attempts, giving up
- xAI OAuth discovery failed ({status}): {body}
- unknown provider family {family:?}
- Failed to resolve host '{host}'
- Generated image URL targets a local or non-global host
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/3f68d12dea5a4da0.
Report an issue: GitHub.