aaif-goose/goose · error
Failed to decode base64 content: {}
Error message
Failed to decode base64 content: {} What it means
The recipe file's `content` field from GitHub's contents API is base64, but base64::decode failed after stripping only '\n'. Two concrete causes: the response contains '\r\n' line breaks (the code strips '\n' but leaves '\r', an invalid base64 character), or the `encoding` field is "none" (files 1–100 MB), where `content` holds non-base64 data.
Source
Thrown at crates/goose-cli/src/recipes/github_recipe.rs:359
.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),
title: Some(recipe.title),
description: Some(recipe.description),
});
}
Err(anyhow!("Failed to get recipe content from GitHub"))
}View on GitHub (pinned to 3810898a74)
Solutions
- Check the file size via the listing's `size` field; if it exceeds 1048576 bytes, shrink the recipe or fetch it another way — the contents API will not deliver usable base64.
- If size is small, inspect the raw content field for '\r' characters and strip them too.
- Prefer fetching raw content (`gh api -H 'Accept: application/vnd.github.raw' ...`) which bypasses base64 entirely, and suggest that upstream adopt it.
Example fix
// before (crates/goose-cli/src/recipes/github_recipe.rs)
let content_bytes = general_purpose::STANDARD
.decode(content_b64.replace('\n', ""))
.map_err(|e| anyhow!("Failed to decode base64 content: {}", e))?;
// after: strip CR as well and reject encoding != "base64"
if file_info.get("encoding").and_then(|e| e.as_str()) != Some("base64") {
return Err(anyhow!("File too large for contents API (encoding != base64)"));
}
let content_bytes = general_purpose::STANDARD
.decode(content_b64.replace(['\n', '\r'], ""))
.map_err(|e| anyhow!("Failed to decode base64 content: {}", e))?; Defensive patterns
Strategy: validation
Validate before calling
# reject files the contents API can't inline as base64
size=$(gh api "repos/${REPO}/contents/${DIR}/recipe.yaml" --jq '.size')
enc=$(gh api "repos/${REPO}/contents/${DIR}/recipe.yaml" --jq '.encoding')
[ "$size" -lt 1048576 ] && [ "$enc" = "base64" ] || echo "too large / not base64 — fetch raw instead" Try / catch
match decode_content(&file_info) {
Err(e) if e.to_string().contains("Failed to decode base64") => {
// fall back to raw media-type fetch
fetch_raw(repo, dir, file).await
}
r => r,
} Prevention
- Keep recipe files well under 1 MB.
- Prefer `gh api -H 'Accept: application/vnd.github.raw'` in your own fetchers to skip base64.
- Normalize CRLF in base64 payloads before decoding.
When it happens
Trigger: A base64 payload wrapped with CRLF line endings (proxies, some gh transports) leaving stray '\r' characters; a recipe file larger than 1 MB where GitHub returns encoding="none" so content is not base64 at all.
Common situations: Recipe.yaml files that grew past 1 MB (embedded blobs, giant prompts); HTTP intermediaries normalizing line endings to CRLF.
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 convert content to string: {}
- Failed to get recipe content from GitHub
- No recipe file found in {} (looked for extensions: {:?})
- Failed to parse directory contents: {}
- No recipe file found in directory: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/5c78ad4a113b4483.
Report an issue: GitHub.