aaif-goose/goose · error
Failed to parse recipe from file.
Error message
Failed to parse recipe from file.
What it means
Shown by the schedule modal in the goose desktop app when the file was read successfully (found is true, no error) but parseRecipeFromFile returned a falsy value. parseRecipeFromFile delegates to the ACP recipe parser; when the content is empty or is YAML that does not represent a recipe, the parser can return null/undefined rather than throw, and this branch converts that into the localized 'Failed to parse recipe from file.' message. Distinct from error 45: the bytes were read; they just are not a valid goose recipe.
Source
Thrown at ui/desktop/src/components/schedule/ScheduleModal.tsx:143
}
}
}
}, [isOpen, schedule, initialDeepLink, handleDeepLinkChange]);
const handleBrowseFile = async () => {
const fileResponse = await window.electron.selectRecipeFile();
if (fileResponse) {
if (fileResponse.filePath.endsWith('.yaml') || fileResponse.filePath.endsWith('.yml')) {
setRecipeSourcePath(fileResponse.filePath);
setInternalValidationError(null);
try {
if (!fileResponse.found || fileResponse.error) {
throw new Error(intl.formatMessage(i18n.failedReadFile));
}
const recipe = await parseRecipeFromFile(fileResponse.file);
if (!recipe) {
throw new Error(intl.formatMessage(i18n.failedParseRecipe));
}
setParsedRecipe(recipe);
if (recipe.title) {
setScheduleIdFromTitle(recipe.title);
}
} catch (e) {
setParsedRecipe(null);
setInternalValidationError(
e instanceof Error ? e.message : intl.formatMessage(i18n.failedParseRecipe)
);
}
} else {
setInternalValidationError(intl.formatMessage(i18n.invalidFileType));
}
}
};
const handleLocalSubmit = async (event: FormEvent) => {View on GitHub (pinned to 3810898a74)
Solutions
- Open the selected YAML and confirm it is a goose recipe: top-level title/description plus instructions or prompt
- Get known-good YAML by exporting a working recipe (goose CLI or desktop recipe UI) and comparing structure
- Make sure the file is non-empty and starts at column 0 (no stray BOM or leading blank document markers)
Defensive patterns
Strategy: validation
Validate before calling
const text = fileResponse.file ?? ''; const looksLikeGooseRecipe = text.trim().length > 0 && /(^|\n)(instructions|prompt):/.test(text) && /(^|\n)(title|name):/.test(text);
Type guard
const isParsedRecipe = (r: Recipe | null | undefined): r is Recipe => Boolean(r) && Boolean((r as Recipe).title);
Try / catch
try {
const recipe = await parseRecipeFromFile(fileResponse.file);
if (!isParsedRecipe(recipe)) {
setInternalValidationError(intl.formatMessage(i18n.failedParseRecipe));
return;
}
setParsedRecipe(recipe);
} catch (e) {
setInternalValidationError(e instanceof Error ? e.message : intl.formatMessage(i18n.failedParseRecipe));
} Prevention
- Author recipes by exporting a working recipe and editing the YAML
- Eyeball the YAML for top-level title/description plus instructions or prompt before scheduling
- Do not rely on the .yaml extension alone — the dialog filters on extension, not content
When it happens
Trigger: Selecting an empty .yaml file; selecting YAML that parses but has no recipe structure (missing title/instructions/prompt at the top level); selecting a YAML front-matter fragment or unrelated config file renamed to .yml.
Common situations: Hand-authoring recipe YAML for the scheduler without the required recipe fields; exporting partial recipes from other tools; picking a CI or docker-compose YAML by mistake because the dialog filters only on extension.
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
- Invalid deeplink or recipe format
- Failed to read the selected file.
- {} recipe file is invalid: {}
- Failed to open recipe: {}
- Missing 'instructions' in json response
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/bbe7717ce2bd5246.
Report an issue: GitHub.