aaif-goose/goose · error
Invalid repo id '{}': expected owner/name
Error message
Invalid repo id '{}': expected owner/name What it means
split_repo_id requires a '/' in the repo id (split_once('/')) and is used by model_repo and download_gguf_to_hf_cache to build HF API/download requests. Bare names or empty strings fail here. Note only the presence of a slash is checked: '/name' or 'a/b/c' pass this check with empty or compound parts and fail later at the HF API with a 404-style error instead.
Source
Thrown at crates/goose-local-inference/src/hf_models.rs:1510
}
async fn hf_client() -> Result<HFClient> {
let mut builder = HFClient::builder().user_agent("goose-ai-agent");
if let Some(token) = optional_hf_token(huggingface_auth::resolve_token_async()).await {
builder = builder.token(token);
}
builder.build().map_err(Into::into)
}
fn model_repo(client: &HFClient, repo_id: &str) -> Result<HFRepository<RepoTypeModel>> {
let (owner, name) = split_repo_id(repo_id)?;
Ok(client.model(owner, name))
}
fn split_repo_id(repo_id: &str) -> Result<(&str, &str)> {
repo_id
.split_once('/')
.ok_or_else(|| anyhow::anyhow!("Invalid repo id '{}': expected owner/name", repo_id))
}
async fn search_mlx_models(query: &str, limit: usize) -> Result<Vec<HfModelInfo>> {
let mut results = search_mlx_models_with_query(query, limit).await?;
if !query.contains('/') {
results
.extend(search_mlx_models_with_query(&format!("mlx-community/{query}"), limit).await?);
results.extend(search_mlx_models_with_query(&format!("google/{query}"), limit).await?);
}
dedupe_models(&mut results);
results.truncate(limit);
Ok(results)
}
async fn search_mlx_models_with_query(query: &str, limit: usize) -> Result<Vec<HfModelInfo>> {
let client = hf_client().await?;
let stream = client
.list_models()View on GitHub (pinned to 3810898a74)
Solutions
- Use the full 'owner/name' id exactly as it appears in the huggingface.co URL, e.g. 'bartowski/Llama-3.2-1B-Instruct-GGUF'
- If you only have a bare name, resolve it through model search first to obtain the full id
- Normalize/validate ids at your config boundary so partial ids never reach the resolver
Example fix
// before
let repo = client.model(repo_id, String::new()); // or passing a bare name downstream
// after: validate shape once at the edge
let (owner, name) = repo_id
.split_once('/')
.filter(|(o, n)| !o.is_empty() && !n.is_empty() && !n.contains('/'))
.with_context(|| format!("expected 'owner/name', got '{repo_id}'"))?; Defensive patterns
Strategy: validation
Validate before calling
anyhow::ensure!(
matches!(repo_id.split_once('/'), Some((o, n)) if !o.is_empty() && !n.is_empty() && !n.contains('/')),
"repo id must be 'owner/name', got '{repo_id}'"
); Type guard
fn is_valid_repo_id(repo_id: &str) -> bool {
matches!(repo_id.split_once('/'), Some((owner, name)) if !owner.is_empty() && !name.is_empty() && !name.contains('/'))
} Try / catch
match split_repo_id_result {
Err(e) if e.to_string().contains("expected owner/name") => {
// resolve the bare name through model search to get the full id
}
other => other,
} Prevention
- Store and pass full 'owner/name' ids end to end; never strip the owner segment
- Validate the id shape where it enters your system (config load, CLI args)
- Copy ids from the huggingface.co URL to avoid transcription drift
When it happens
Trigger: Calling the GGUF download/resolve path with a bare model name like 'Llama-3.2-1B-Instruct-GGUF', an empty string, or a value trimmed of its owner prefix by UI code.
Common situations: Search-driven flows returning bare names; configs storing only the short title; copy-paste from HF URLs that drops the owner segment.
Related errors
- Invalid model spec '{}': expected format 'user/repo:quantiza
- Cannot parse shard total from '{}'
- Model spec '{}' is ambiguous; choose one of: {}
- Download failed after {} retries: {}
- Failed to download: HTTP {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/c3dd82beb7547d35.
Report an issue: GitHub.