aaif-goose/goose · error
Failed to access recipe file: {}/{}
Error message
Failed to access recipe file: {}/{} What it means
`gh api repos/{repo}/contents/{dir}/{recipe_filename}` ran but exited non-zero while fetching the recipe file itself. This is an HTTP-level failure surfaced through gh: 404 when the path is wrong (case-sensitive, or the file was renamed between the listing and the fetch), 401/403 for auth or permission problems on private repos, and 403 for primary/secondary rate limits.
Source
Thrown at crates/goose-cli/src/recipes/github_recipe.rs:344
Err(anyhow!("No recipe file found in directory: {}", dir_name))
}
fn get_github_recipe_info(repo: &str, dir_name: &str, recipe_filename: &str) -> Result<RecipeInfo> {
use serde_json::Value;
use std::process::Command;
// Get the recipe file content
let output = Command::new("gh")
.args([
"api",
&format!("repos/{}/contents/{}/{}", repo, dir_name, recipe_filename),
])
.set_no_window()
.output()
.map_err(|e| anyhow!("Failed to get recipe file content: {}", e))?;
if !output.status.success() {
return Err(anyhow!(
"Failed to access recipe file: {}/{}",
dir_name,
recipe_filename
));
}
let file_info: Value = serde_json::from_slice(&output.stdout)
.map_err(|e| anyhow!("Failed to parse file info: {}", e))?;
if let Some(content_b64) = file_info.get("content").and_then(|c| c.as_str()) {
// Decode base64 content
use base64::{engine::general_purpose, Engine as _};
let content_bytes = general_purpose::STANDARD
.decode(content_b64.replace('\n', ""))
.map_err(|e| anyhow!("Failed to decode base64 content: {}", e))?;
let content = String::from_utf8(content_bytes)
.map_err(|e| anyhow!("Failed to convert content to string: {}", e))?;View on GitHub (pinned to 3810898a74)
Solutions
- Run the exact URL manually: `gh api "repos/{repo}/contents/{dir}/{file}"` and read the HTTP status it reports.
- If rate-limited (403 with rate limit message), wait for the reset window or authenticate via `gh auth login` to raise the limit.
- If 404, verify the file name and its casing against the directory listing.
- If 401/403 on a private repo, re-authenticate or grant the token repo access.
Example fix
# before $ goose recipe info owner/private-repo/my-recipe Error: Failed to access recipe file: my-recipe/recipe.yaml # after $ gh auth status # shows token lacks repo scope $ gh auth refresh -h github.com -s repo $ goose recipe info owner/private-repo/my-recipe
Defensive patterns
Strategy: retry
Validate before calling
# confirm the exact path resolves before goose fetches it (case-sensitive)
gh api "repos/${REPO}/contents/${DIR}/recipe.yaml" --jq '.name' Try / catch
for attempt in 0..3 {
match fetch_recipe_file(repo, dir, file) {
Err(e) if e.to_string().contains("Failed to access recipe file") && attempt < 2 => {
tokio::time::sleep(Duration::from_secs(2u64.pow(attempt))).await; // rate-limit backoff
}
r => break r,
}
} Prevention
- Authenticate gh (higher rate limits) before bulk recipe scans.
- Keep filenames stable and lowercase to avoid case-mismatch 404s.
- Back off on 403 rate-limit responses instead of hammering the API.
When it happens
Trigger: Recipe file renamed or deleted between the directory listing and this second API call (race); unauthenticated gh hitting GitHub's rate limit while listing many recipes; accessing a private repo without an authorized token; wrong-case path segments on case-sensitive APIs.
Common situations: Scanning large recipe collections until the unauthenticated rate limit trips; upstream repos moving files; tokens lacking repo scope for private recipe repos.
Related errors
- Failed to parse directory contents: {}
- GitHub API returned ${response.status}: ${response.statusTex
- No recipe file found in {} (looked for extensions: {:?})
- No recipe file found in directory: {}
- Failed to decode base64 content: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/4d2a557cb3f13acd.
Report an issue: GitHub.