{"record":{"id":"d698506840f73e98","repo":"gastownhall/beads","slug":"parse-recipes-toml-w","errorCode":null,"errorMessage":"parse recipes.toml: %w","messagePattern":"parse recipes\\.toml: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/recipes/recipes.go","lineNumber":159,"sourceCode":"// UserRecipes holds recipes loaded from user config file.\ntype UserRecipes struct {\n\tRecipes map[string]Recipe `toml:\"recipes\"`\n}\n\n// LoadUserRecipes loads recipes from .beads/recipes.toml if it exists.\nfunc LoadUserRecipes(beadsDir string) (map[string]Recipe, error) {\n\tpath := filepath.Join(beadsDir, \"recipes.toml\")\n\tdata, err := os.ReadFile(path) // #nosec G304 -- path is constructed from validated beadsDir\n\tif os.IsNotExist(err) {\n\t\treturn nil, nil // No user recipes, that's fine\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read recipes.toml: %w\", err)\n\t}\n\n\tvar userRecipes UserRecipes\n\tif err := toml.Unmarshal(data, &userRecipes); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse recipes.toml: %w\", err)\n\t}\n\n\t// Set defaults for user recipes\n\tfor name, recipe := range userRecipes.Recipes {\n\t\tif recipe.Type == \"\" {\n\t\t\trecipe.Type = TypeFile\n\t\t}\n\t\tif recipe.Name == \"\" {\n\t\t\trecipe.Name = name\n\t\t}\n\t\tuserRecipes.Recipes[name] = recipe\n\t}\n\n\treturn userRecipes.Recipes, nil\n}\n\n// GetAllRecipes returns merged built-in and user recipes.\n// User recipes override built-in recipes with the same name.","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/recipes/recipes.go#L141-L177","documentation":"The user's recipes.toml was read successfully but could not be parsed as TOML. The toml.Unmarshal error is wrapped so you can see the malformed line from the original parser message.","triggerScenarios":"toml.Unmarshal fails on the contents of <beadsDir>/recipes.toml — invalid TOML syntax, wrong types for Recipe fields, or an unexpected top-level structure.","commonSituations":"Hand-edited recipes.toml with a missing quote, duplicate key, tabs in wrong place, or a value of the wrong type (e.g. a string where a map of recipes is expected); file truncated by a crashed editor.","solutions":["Read the wrapped TOML error for the exact line/column and fix the syntax in .beads/recipes.toml","Validate the file with a TOML linter or `tomlq . .beads/recipes.toml`","Compare against a known-good recipes.toml structure ([recipes.<name>] with name/path/type fields)","Restore the file from backup or delete it to fall back to built-in recipes"],"exampleFix":"// before (broken)\n[recipes.myrecipe\nname = \"x\"\n// after\n[recipes.myrecipe]\nname = \"x\"","handlingStrategy":"validation","validationCode":"// Validate TOML before handing it to the app\nvar probe map[string]any\nif err := toml.Unmarshal(data, &probe); err != nil {\n\treturn fmt.Errorf(\"recipes.toml invalid: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"userRecipes, err := LoadUserRecipes(ctx, beadsDir)\nif err != nil && strings.HasPrefix(err.Error(), \"parse recipes.toml\") {\n\t// fall back to built-ins, surface the parse error to the user\n\twarn(err)\n\tuserRecipes = nil\n}","preventionTips":["Run a TOML linter after hand-editing recipes.toml","Match the documented [recipes.<name>] schema exactly","Avoid manual edits to files written by the encoder; use `bd recipe` commands","Keep a backup before restructuring recipes.toml"],"tags":["toml","config","parse-error"],"backgroundTag":"config-parse-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}