{"record":{"id":"b184abd6f59f86c6","repo":"gastownhall/beads","slug":"applying-expansions-w","errorCode":null,"errorMessage":"applying expansions: %w","messagePattern":"applying expansions: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/cook.go","lineNumber":196,"sourceCode":"\tresolved.Steps = controlFlowSteps\n\n\t// Apply advice transformations\n\tif len(resolved.Advice) > 0 {\n\t\tresolved.Steps = formula.ApplyAdvice(resolved.Steps, resolved.Advice)\n\t}\n\n\t// Apply inline step expansions\n\tinlineExpandedSteps, err := formula.ApplyInlineExpansions(resolved.Steps, parser)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"applying inline expansions: %w\", err)\n\t}\n\tresolved.Steps = inlineExpandedSteps\n\n\t// Apply expansion operators\n\tif resolved.Compose != nil && (len(resolved.Compose.Expand) > 0 || len(resolved.Compose.Map) > 0) {\n\t\texpandedSteps, err := formula.ApplyExpansions(resolved.Steps, resolved.Compose, parser)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"applying expansions: %w\", err)\n\t\t}\n\t\tresolved.Steps = expandedSteps\n\t}\n\n\t// Apply aspects from compose.aspects\n\tif resolved.Compose != nil && len(resolved.Compose.Aspects) > 0 {\n\t\tfor _, aspectName := range resolved.Compose.Aspects {\n\t\t\taspectFormula, err := parser.LoadByName(aspectName)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"loading aspect %q: %w\", aspectName, err)\n\t\t\t}\n\t\t\tif aspectFormula.Type != formula.TypeAspect {\n\t\t\t\treturn nil, fmt.Errorf(\"%q is not an aspect formula (type=%s)\", aspectName, aspectFormula.Type)\n\t\t\t}\n\t\t\tif len(aspectFormula.Advice) > 0 {\n\t\t\t\tresolved.Steps = formula.ApplyAdvice(resolved.Steps, aspectFormula.Advice)\n\t\t\t}\n\t\t}","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/cook.go#L178-L214","documentation":"cmd/bd/cook.go:196 wraps errors from formula.ApplyExpansions(resolved.Steps, resolved.Compose, parser), which processes compose-level expansion operators (compose.expand and compose.map) to fan steps out over collections or substitute them. It only runs when Compose declares expand/map entries; failure means one of those operators is malformed or references something unresolvable (bad expression, missing target formula, invalid map key).","triggerScenarios":"A formula with compose.expand or compose.map entries where the expansion expression doesn't evaluate, the expanded target formula can't be loaded/parsed, or a map entry references a nonexistent parameter or step.","commonSituations":"Defining compose.map with a variable the target formula doesn't accept; typo'd formula name in compose.expand; generating permutations from an empty/misused collection expression; upgrading bd and hitting stricter expansion validation than when the formula was written.","solutions":["Inspect compose.expand/compose.map in the formula and compare each entry's expression and targets against the wrapped error message.","Verify every expand target formula exists in the registry and parses standalone.","Confirm map keys match parameters actually declared/used by the expanded steps.","Simplify to a single expand/map entry and re-run to isolate the failing operator."],"exampleFix":"// before (compose block)\nexpand:\n  - formula: matrix-run   # never defined\n// after\nexpand:\n  - formula: run-per-env   # exists in .beads/formulas/","handlingStrategy":"validation","validationCode":"func expansionsResolvable(c *formula.ComposeRules, load func(string) (*formula.Formula, error)) error {\n\tif c == nil {\n\t\treturn nil\n\t}\n\tfor _, e := range c.Expand {\n\t\tif _, err := load(e.Formula); err != nil {\n\t\t\treturn fmt.Errorf(\"expand target %q unloadable: %w\", e.Formula, err)\n\t\t}\n\t}\n\tfor _, m := range c.Map {\n\t\tif m.Formula != \"\" {\n\t\t\tif _, err := load(m.Formula); err != nil {\n\t\t\t\treturn fmt.Errorf(\"map target %q unloadable: %w\", m.Formula, err)\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func hasValidExpansions(c *formula.ComposeRules, exists func(string) bool) bool {\n\tif c == nil {\n\t\treturn true\n\t}\n\tfor _, e := range c.Expand {\n\t\tif !exists(e.Formula) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}","tryCatchPattern":"expanded, err := formula.ApplyExpansions(resolved.Steps, resolved.Compose, parser)\nif err != nil {\n\treturn fmt.Errorf(\"compose expand/map is invalid: %w\", err)\n}","preventionTips":["Ensure every compose.expand/compose.map target formula exists and parses in the target environment.","Keep map keys in sync with parameters the expanded formula actually declares.","Test expansions with a minimal collection first to surface expression errors early.","After bd upgrades, re-validate formulas using expand/map in CI to catch stricter validation."],"tags":["formula","expansion","compose","validation"],"backgroundTag":"formula-expansion-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}