{"record":{"id":"059e0d4acb502fed","repo":"aaif-goose/goose","slug":"invalid-repository-name-format","errorCode":null,"errorMessage":"Invalid repository name format","messagePattern":"Invalid repository name format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/recipes/github_recipe.rs","lineNumber":157,"sourceCode":"            }\n            _ => child.push('_'),\n        }\n    }\n\n    if child.is_empty() {\n        \"_\".to_string()\n    } else {\n        child\n    }\n}\n\nfn get_local_repo_path(\n    local_repo_parent_path: &Path,\n    recipe_repo_full_name: &str,\n) -> Result<PathBuf> {\n    let (owner, repo_name) = recipe_repo_full_name\n        .split_once('/')\n        .ok_or_else(|| anyhow::anyhow!(\"Invalid repository name format\"))?;\n    let local_repo_path = local_repo_parent_path\n        .to_path_buf()\n        .join(temp_child_name(&format!(\"{owner}/{repo_name}\")));\n    Ok(local_repo_path)\n}\n\nfn ensure_repo_cloned(recipe_repo_full_name: &str) -> Result<PathBuf> {\n    let local_repo_parent_path = env::temp_dir();\n    if !local_repo_parent_path.exists() {\n        std::fs::create_dir_all(local_repo_parent_path.clone())?;\n    }\n    let local_repo_path = get_local_repo_path(&local_repo_parent_path, recipe_repo_full_name)?;\n\n    if local_repo_path.join(\".git\").exists() {\n        Ok(local_repo_path)\n    } else {\n        let error_message: String = format!(\"Failed to clone repo: {}\", recipe_repo_full_name);\n        let status = Command::new(\"gh\")","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/recipes/github_recipe.rs#L139-L175","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\nexport GOOSE_RECIPE_GITHUB_REPO=my-recipes\n\n# after\nexport GOOSE_RECIPE_GITHUB_REPO=block/my-recipes","handlingStrategy":"validation","validationCode":"# Validate the config value before any goose run\nrepo=\"${GOOSE_RECIPE_GITHUB_REPO:-}\"\ncase \"$repo\" in\n  */*) : ;;                    # contains a slash: OK for owner/repo\n  *) echo \"GOOSE_RECIPE_GITHUB_REPO must be owner/repo (got: '$repo')\" >&2; exit 2 ;;\nesac","typeGuard":"// Rust: narrowing guard for the repo full-name format\nfn is_valid_repo_full_name(value: &str) -> bool {\n    match value.split_once('/') {\n        Some((owner, repo)) => !owner.is_empty() && !repo.is_empty() && !repo.contains('/'),\n        None => false,\n    }\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["goose-cli","configuration","validation","github"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}