{"record":{"id":"3f31024167688e9e","repo":"aaif-goose/goose","slug":"failed-to-access-directory","errorCode":null,"errorMessage":"Failed to access directory: {}","messagePattern":"Failed to access directory: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/recipes/github_recipe.rs","lineNumber":306,"sourceCode":"        }\n    }\n\n    Ok(recipes)\n}\n\nfn check_github_directory_for_recipe(repo: &str, dir_name: &str) -> Result<RecipeInfo> {\n    use serde_json::Value;\n    use std::process::Command;\n\n    // Check directory contents for recipe files\n    let output = Command::new(\"gh\")\n        .args([\"api\", &format!(\"repos/{}/contents/{}\", repo, dir_name)])\n        .set_no_window()\n        .output()\n        .map_err(|e| anyhow!(\"Failed to check directory contents: {}\", e))?;\n\n    if !output.status.success() {\n        return Err(anyhow!(\"Failed to access directory: {}\", dir_name));\n    }\n\n    let contents: Value = serde_json::from_slice(&output.stdout)\n        .map_err(|e| anyhow!(\"Failed to parse directory contents: {}\", e))?;\n\n    if let Some(items) = contents.as_array() {\n        for item in items {\n            if let Some(name) = item.get(\"name\").and_then(|n| n.as_str()) {\n                if RECIPE_FILE_EXTENSIONS\n                    .iter()\n                    .any(|ext| name == format!(\"recipe.{}\", ext))\n                {\n                    // Found a recipe file, get its content\n                    return get_github_recipe_info(repo, dir_name, name);\n                }\n            }\n        }\n    }","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/recipes/github_recipe.rs#L288-L324","documentation":"check_github_directory_for_recipe treats a non-zero exit of `gh api repos/<repo>/contents/<dir>` as this error, naming the directory that failed (crates/goose-cli/src/recipes/github_recipe.rs:305-307). gh's stderr with the concrete HTTP reason appears above it. Common causes: the directory does not exist (repo changed since the parent listing), is a file not a dir, no access, or rate limiting during discovery.","triggerScenarios":"Repo layout changes between the contents listing and the per-directory probe; symlinks/submodules the API lists but cannot enumerate; private/protected paths the token cannot read; secondary rate limits when probing many directories quickly.","commonSituations":"Recipe repo being edited while goose lists it, large repos triggering GitHub rate limits during discovery, or names with characters needing URL encoding (spaces, '#') that break the naive path concatenation in the API URL.","solutions":["Check the directory manually: `gh api repos/<owner>/<repo>/contents/<dir-name>` — the returned status explains whether it is 404, 403, or encoding-related","Rename repo directories to URL-safe names (lowercase, hyphens) if special characters are involved","If rate-limited during discovery of a large repo, wait for reset or authenticate with a higher-limit token; re-run after the repo layout settles"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# Validate each candidate directory is API-addressable before discovery\ngh repo view \"$GOOSE_RECIPE_GITHUB_REPO\" --json name >/dev/null\ngh api \"repos/$GOOSE_RECIPE_GITHUB_REPO/contents\" --jq '.[] | select(.type==\"dir\") | .name' \\\n  | while read -r d; do gh api \"repos/$GOOSE_RECIPE_GITHUB_REPO/contents/$d\" >/dev/null || echo \"bad dir: $d\"; done","typeGuard":null,"tryCatchPattern":"// Rust: skip directories that fail to probe instead of aborting all discovery\nmatch check_github_directory_for_recipe(repo, name) {\n    Ok(info) => recipes.push(info),\n    Err(e) => tracing::warn!(\"skipping directory {name}: {e}\"),\n}","preventionTips":["Use URL-safe directory names (lowercase, hyphens, no spaces/#) in recipe repos","Avoid editing the recipe repo layout while discovery runs","Watch rate limits when probing many directories; cache or batch where possible"],"tags":["goose-cli","github-api","http-error","recipes"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}