aaif-goose/goose · error
Failed to parse file info: {}
Error message
Failed to parse file info: {} What it means
After successfully fetching the single recipe file's metadata, `serde_json::from_slice` on gh's stdout failed — the response body was not valid JSON. The directory listing call succeeded, so auth is fine; this points to a mangled response for the file-content endpoint, such as warnings injected into stdout, truncated output, or non-JSON error bodies from a proxy.
Source
Thrown at crates/goose-cli/src/recipes/github_recipe.rs:352
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))?;
// Parse the recipe content
let (recipe, _) = parse_recipe_content(&content, Some(format!("{}/{}", repo, dir_name)))?;
return Ok(RecipeInfo {
name: dir_name.to_string(),
source: RecipeSource::GitHub,
path: format!("{}/{}", repo, dir_name),View on GitHub (pinned to 3810898a74)
Solutions
- Reproduce manually: `gh api "repos/{repo}/contents/{dir}/{file}" | head -c 300` and look for non-JSON prefix lines.
- Remove gh aliases or wrappers (check `gh alias list`) that decorate output.
- Update gh to a version that keeps notices on stderr.
- Retry after a short wait if a transient secondary rate-limit notice was interleaved.
Example fix
# before: gh alias wraps output $ gh alias list api: api --paginate || echo done # extra text pollutes stdout # after $ gh alias delete api $ goose recipe info owner/repo/my-recipe
Defensive patterns
Strategy: validation
Validate before calling
# ensure the file endpoint returns pure JSON before relying on goose's parse
gh api "repos/${REPO}/contents/${DIR}/recipe.yaml" | jq -e 'has("content")' >/dev/null \
|| echo "response is not clean JSON — check gh aliases/proxies" Try / catch
if let Err(e) = get_recipe_info(repo, dir) {
if e.to_string().starts_with("Failed to parse file info") {
eprintln!("gh stdout polluted — inspect `gh api .../recipe.yaml` output");
}
return Err(e);
} Prevention
- Avoid gh aliases/wrappers that print extra lines to stdout.
- Use `gh api --silent`-style hygiene in your own tooling around gh.
When it happens
Trigger: gh emitting a deprecation or secondary-rate-limit warning line into stdout before the JSON body; a proxy or GH_HOST gateway rewriting the response; extremely large responses being truncated by pipe buffering limits.
Common situations: Corporate proxies modifying responses; gh versions that print notices to stdout instead of stderr; piping through wrappers (gh aliases, tee) that add text.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse directory contents: {}
- Failed to parse OpenAI evaluation response after {max_retrie
- Failed to parse tie-breaker response after {max_retries} att
- Failed to parse GitHub API response: {}
- Failed to get recipe file content: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/6f7cf48e411a4ae2.
Report an issue: GitHub.