aaif-goose/goose · error
Invalid repository name format
Error message
Invalid repository name format
What it means
get_local_repo_path computes the on-disk clone location for the recipe repo by splitting GOOSE_RECIPE_GITHUB_REPO's value on the first '/' (crates/goose-cli/src/recipes/github_recipe.rs:160-167). split_once returns None when the value contains no slash, and this error replaces it — it is pure input validation on the config value, before any network or git activity.
Source
Thrown at crates/goose-cli/src/recipes/github_recipe.rs:157
}
_ => child.push('_'),
}
}
if child.is_empty() {
"_".to_string()
} else {
child
}
}
fn get_local_repo_path(
local_repo_parent_path: &Path,
recipe_repo_full_name: &str,
) -> Result<PathBuf> {
let (owner, repo_name) = recipe_repo_full_name
.split_once('/')
.ok_or_else(|| anyhow::anyhow!("Invalid repository name format"))?;
let local_repo_path = local_repo_parent_path
.to_path_buf()
.join(temp_child_name(&format!("{owner}/{repo_name}")));
Ok(local_repo_path)
}
fn ensure_repo_cloned(recipe_repo_full_name: &str) -> Result<PathBuf> {
let local_repo_parent_path = env::temp_dir();
if !local_repo_parent_path.exists() {
std::fs::create_dir_all(local_repo_parent_path.clone())?;
}
let local_repo_path = get_local_repo_path(&local_repo_parent_path, recipe_repo_full_name)?;
if local_repo_path.join(".git").exists() {
Ok(local_repo_path)
} else {
let error_message: String = format!("Failed to clone repo: {}", recipe_repo_full_name);
let status = Command::new("gh")View on GitHub (pinned to 3810898a74)
Solutions
- Set the variable to the full owner/repo form: export GOOSE_RECIPE_GITHUB_REPO=owner/repo
- Check the current value: `echo "$GOOSE_RECIPE_GITHUB_REPO"` — empty output means it is unset-but-defaulted or exported blank somewhere (shell profile, .env, CI variables)
- If you use a URL form, strip it down to owner/repo before setting the variable
Example fix
# before export GOOSE_RECIPE_GITHUB_REPO=my-recipes # after export GOOSE_RECIPE_GITHUB_REPO=block/my-recipes
Defensive patterns
Strategy: validation
Validate before calling
# Validate the config value before any goose run
repo="${GOOSE_RECIPE_GITHUB_REPO:-}"
case "$repo" in
*/*) : ;; # contains a slash: OK for owner/repo
*) echo "GOOSE_RECIPE_GITHUB_REPO must be owner/repo (got: '$repo')" >&2; exit 2 ;;
esac Type guard
// Rust: narrowing guard for the repo full-name format
fn is_valid_repo_full_name(value: &str) -> bool {
match value.split_once('/') {
Some((owner, repo)) => !owner.is_empty() && !repo.is_empty() && !repo.contains('/'),
None => false,
}
} Prevention
- Always set GOOSE_RECIPE_GITHUB_REPO as owner/repo, never a bare repo name or URL
- Add a startup assertion in wrapper scripts that fails fast on malformed values
When it happens
Trigger: GOOSE_RECIPE_GITHUB_REPO is set to a value without an owner/repo slash: "my-recipes", "", or a full URL like "https://github.com/owner/repo" also fails? — no: a full URL contains '/' and splits (incorrectly) — the direct trigger is any slash-less value. Reachable from clone, fetch, and cleanup paths.
Common situations: Copy/paste of just the repo name instead of owner/repo, an empty env var (GOOSE_RECIPE_GITHUB_REPO="") exported by a script, or whitespace/format drift in .env files.
Related errors
- External ACP backend URL is required
- External ACP backend URL must use http: or https:, got ${url
- External ACP backend URL must not include query parameters o
- External ACP backend URL must be the base URL before /acp
- Could not retrieve sub-recipe '{}': {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/059e0d4acb502fed.
Report an issue: GitHub.