nikivdev/code · error · anyhow::Error
multiple matches for '{}': {}. Use owner/repo.
Error message
multiple matches for '{}': {}. Use owner/repo. What it means
Raised when a bare repo `name` matches more than one locally cloned repo (src/deps.rs:1334), e.g. `foo` matching both `acme/foo` and `other/foo`. Because the tool cannot disambiguate, it bails and lists every matching `owner/repo` pair, asking the user to qualify the name.
Source
Thrown at src/deps.rs:1334
});
}
}
if matches.is_empty() {
bail!(
"repo '{}' not found under {}. Use owner/repo or run: f repos clone <url>",
name,
root.display()
);
}
if matches.len() > 1 {
let options = matches
.iter()
.map(|repo| format!("{}/{}", repo.owner, repo.repo))
.collect::<Vec<_>>()
.join(", ");
bail!(
"multiple matches for '{}': {}. Use owner/repo.",
name,
options
);
}
Ok(matches.remove(0))
}
fn upsert_repo_manifest(path: &Path, root: &str, repo: &repos::RepoRef, url: &str) -> Result<()> {
let mut doc = if path.exists() {
let contents = std::fs::read_to_string(path)
.with_context(|| format!("failed to read {}", path.display()))?;
toml::from_str::<Value>(&contents).unwrap_or(Value::Table(Map::new()))
} else {
Value::Table(Map::new())
};
View on GitHub (pinned to a747e741ae)
Solutions
- Retry with the qualified form shown in the message, e.g. `acme/foo`
- Remove or rename the duplicate clone you no longer need
- Keep a unique local directory name when cloning (clone into an owner-prefixed directory)
- Update any scripts/aliases to use owner/repo form
Example fix
// before f deps open foo error: multiple matches for 'foo': acme/foo, other/foo. Use owner/repo. // after f deps open acme/foo
Defensive patterns
Strategy: validation
Validate before calling
let short = name.rsplit('/').next().unwrap();
let count = std::fs::read_dir(repos_root)?.filter_map(|e| e.ok())
.filter(|e| e.file_name().to_string_lossy() == short).count();
if count > 1 && !name.contains('/') {
anyhow::bail!("'{name}' is ambiguous ({count} matches); use owner/repo");
} Type guard
fn is_unambiguous(name: &str, repos_root: &Path) -> bool {
if name.contains('/') { return true; }
let short = name.rsplit('/').next().unwrap_or(name);
std::fs::read_dir(repos_root).map(|rd| {
rd.filter_map(|e| e.ok())
.filter(|e| e.file_name().to_string_lossy() == short).count()
}).map(|c| c <= 1).unwrap_or(true)
} Try / catch
match resolve_repo(name) {
Err(e) if e.to_string().contains("multiple matches for") => {
// parse the listed options and pick/prompt
let options = e.to_string().split(": ").nth(1).unwrap_or("");
eprintln!("disambiguate: {options}");
}
other => other?,
} Prevention
- Prefer qualified owner/repo names everywhere
- Delete stale forks/duplicates of same-named repos
- Clone into owner-prefixed directory names
- Audit the repos root after forking operations
When it happens
Trigger: Calling a repo-targeting command with an unqualified name while the repos root contains two or more repos whose leaf name equals `name`; also happens after forking/renaming clones under different owners.
Common situations: Forking a repo so both `origin` and your fork exist locally, two teams owning same-named repos, or bare-name shortcuts that used to be unique before a new clone was added.
Related errors
- AI task '{}' is ambiguous. Matches: - {} Try one of the fu
- repo '{}' not found under {}. Use owner/repo or run: f repos
- ambiguous recipe selector
- Review todo id '{}' is ambiguous
- Todo id '{}' is ambiguous
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/74d75a70ced2b268.
Report an issue: GitHub.