zeroclaw-labs/zeroclaw · error · anyhow::Error
OpenRouter catalog has no entries under vendor prefix {vendo
Error message
OpenRouter catalog has no entries under vendor prefix {vendor_prefix:?} What it means
list_models_for_vendor fetched OpenRouter's public /api/v1/models catalog successfully, then filter_by_vendor found zero model ids starting with "{vendor_prefix}/". The vendor prefix is the segment before the first slash in an OpenRouter id (e.g. anthropic, openai, x-ai); the call errors rather than returning an empty list so callers never mistake 'no such vendor' for 'vendor has no models'.
Source
Thrown at crates/zeroclaw-providers/src/openrouter_catalog.rs:94
.into_iter()
.map(|m| ModelEntryWithPricing {
id: m.id,
pricing: m.pricing,
})
.collect())
}
/// Filter a parsed catalog by vendor prefix, returning the slug portion of
/// each match. Sorted and deduped. Errors if nothing matches. Pure —
/// separated from the live fetch so it can be unit-tested.
pub(crate) fn filter_by_vendor(catalog: &[String], vendor_prefix: &str) -> Result<Vec<String>> {
let needle = format!("{vendor_prefix}/");
let mut slugs: Vec<String> = catalog
.iter()
.filter_map(|id| id.strip_prefix(&needle).map(ToString::to_string))
.collect();
if slugs.is_empty() {
anyhow::bail!("OpenRouter catalog has no entries under vendor prefix {vendor_prefix:?}");
}
slugs.sort();
slugs.dedup();
Ok(slugs)
}
/// Filter an enriched catalog by vendor prefix, returning model entries with
/// pricing. Sorted and deduped by id.
fn filter_by_vendor_with_pricing(
catalog: &[ModelEntryWithPricing],
vendor_prefix: &str,
) -> Result<Vec<zeroclaw_api::model_provider::ModelInfo>> {
use zeroclaw_api::model_provider::ModelInfo;
let needle = format!("{vendor_prefix}/");
let mut models: Vec<ModelInfo> = catalog
.iter()
.filter_map(|e| {
e.id.strip_prefix(&needle).map(|slug| ModelInfo {View on GitHub (pinned to 88bb9c8533)
Solutions
- Pass only the segment before the slash: "anthropic", not "anthropic/" and not the full model id.
- List the full catalog (list_models) and read the real prefixes before filtering.
- If the prefix still fails, confirm the vendor exists at openrouter.ai/models — it may have been renamed or delisted.
Example fix
// before — trailing slash and full-id forms match nothing
list_models_for_vendor("anthropic/").await?;
// after — bare vendor segment
list_models_for_vendor("anthropic").await?; Defensive patterns
Strategy: validation
Validate before calling
// Verify the prefix exists before filtering
let catalog = list_models().await?;
let needle = format!("{vendor}/");
anyhow::ensure!(
catalog.iter().any(|id| id.starts_with(&needle)),
"unknown vendor {vendor}; call list_models() to see real prefixes"
); Type guard
fn vendor_exists(catalog: &[String], vendor: &str) -> bool {
catalog.iter().any(|id| id.starts_with(&format!("{vendor}/")))
} Try / catch
Catch the empty-filter error and fall back to listing the full catalog so the user can pick a real vendor prefix; do not retry — the fetched catalog is cached (OnceCell) and will not change within the process.
Prevention
- Derive vendor dropdowns from the live catalog, not hardcoded lists
- Pass the bare segment before '/' — never a trailing slash or a full model id
- Re-check prefixes after OpenRouter catalog updates
When it happens
Trigger: Calling list_models_for_vendor with a trailing slash ("anthropic/" makes the needle "anthropic//" and matches nothing); a misspelled vendor slug ("google-deepmind" vs "google"); passing a full model id ("anthropic/claude-3.5-sonnet") as the vendor argument.
Common situations: Hardcoding vendor names guessed from marketing names instead of reading actual catalog ids; OpenRouter renaming or delisting a vendor; code written against an old catalog snapshot.
Related errors
- modal custom_id exceeds Discord's 100-char limit; cannot ope
- slash command registration failed for '{name}' ({status}): {
- unknown git channel provider `{other}` (supported: github, g
- git channel `events` routing table ignores every event type;
- invalid forge HTTP method `{}` (expected GET/POST/PATCH/PUT/
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/edf409657c3ed027.
Report an issue: GitHub.