{"record":{"id":"a735d983c356baf5","repo":"gastownhall/beads","slug":"unknown-recipe-s","errorCode":null,"errorMessage":"unknown recipe: %s","messagePattern":"unknown recipe: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/recipes/recipes.go","lineNumber":210,"sourceCode":"\t\tresult[name] = recipe\n\t}\n\n\treturn result, nil\n}\n\n// GetRecipe looks up a recipe by name, checking user recipes first.\nfunc GetRecipe(name string, beadsDir string) (*Recipe, error) {\n\t// Normalize name (lowercase, strip leading/trailing hyphens)\n\tname = strings.ToLower(strings.Trim(name, \"-\"))\n\n\trecipes, err := GetAllRecipes(beadsDir)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\trecipe, ok := recipes[name]\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"unknown recipe: %s\", name)\n\t}\n\n\treturn &recipe, nil\n}\n\n// SaveUserRecipe adds or updates a recipe in .beads/recipes.toml.\nfunc SaveUserRecipe(beadsDir, name, path string) error {\n\trecipesPath := filepath.Join(beadsDir, \"recipes.toml\")\n\n\t// Load existing user recipes\n\tvar userRecipes UserRecipes\n\tdata, err := os.ReadFile(recipesPath) // #nosec G304 -- path is constructed from validated beadsDir\n\tif err == nil {\n\t\tif err := toml.Unmarshal(data, &userRecipes); err != nil {\n\t\t\treturn fmt.Errorf(\"parse recipes.toml: %w\", err)\n\t\t}\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"read recipes.toml: %w\", err)","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/recipes/recipes.go#L192-L228","documentation":"GetRecipe was asked for a recipe name that exists neither in the built-in recipes nor in the user's recipes.toml. There is no default/fuzzy matching — the exact name must exist.","triggerScenarios":"Calling GetRecipe(name) (or the CLI command that uses it) with a name not present in the merged recipe map.","commonSituations":"Typos in the recipe name, a user recipe that failed to load (so only built-ins are visible), referencing a recipe deleted from recipes.toml, or following docs for a recipe renamed in a newer version.","solutions":["List available recipes (ListRecipeNames / the recipes list command) and use an exact existing name","Check that .beads/recipes.toml actually defines the recipe under [recipes.<name>]","Fix typos or case differences in the requested name","If a recipe was renamed in an upgrade, update scripts/docs to the new name"],"exampleFix":"// before\nrecipe, err := recipes.GetRecipe(ctx, \"setup-copilot\")\n// after\nrecipe, err := recipes.GetRecipe(ctx, \"copilot\")","handlingStrategy":"fallback","validationCode":"names, err := recipes.ListRecipeNames(ctx, beadsDir)\nif !slices.Contains(names, wanted) {\n\treturn fmt.Errorf(\"recipe %q not found; available: %v\", wanted, names)\n}","typeGuard":null,"tryCatchPattern":"r, err := GetRecipe(ctx, name)\nif err != nil {\n\tif strings.HasPrefix(err.Error(), \"unknown recipe\") {\n\t\t// suggest closest match\n\t\tsuggestClosest(name, knownNames)\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Discover valid names with ListRecipeNames before lookup","Copy recipe names exactly (watch case and dashes)","Verify user recipes load successfully (no parse errors) before relying on them","After upgrading, re-check for renamed recipes in release notes"],"tags":["recipes","not-found","cli"],"backgroundTag":"unknown-identifier","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}