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

  1. Set the variable to the full owner/repo form: export GOOSE_RECIPE_GITHUB_REPO=owner/repo
  2. 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)
  3. 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

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


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/059e0d4acb502fed. Report an issue: GitHub.