gastownhall/beads · error

applying control flow: %w

Error message

applying control flow: %w

What it means

cmd/bd/cook.go:176 wraps errors from formula.ApplyControlFlow(resolved.Steps, resolved.Compose), which evaluates control-flow operators (loops, branches, gates) declared in the formula into a flat step list. The formula resolved cleanly, but a control-flow construct is invalid: e.g. a loop with no iterable/bad range expression, a branch with missing condition or missing target steps, or a gate referencing an undefined step.

Source

Thrown at cmd/bd/cook.go:176

	f, err := parser.LoadByName(formulaPath)
	if err != nil {
		// Fall back to parsing as a file path
		f, err = parser.ParseFile(formulaPath)
		if err != nil {
			return nil, fmt.Errorf("parsing formula: %w", err)
		}
	}

	// Resolve inheritance
	resolved, err := parser.Resolve(f)
	if err != nil {
		return nil, fmt.Errorf("resolving formula: %w", err)
	}

	// Apply control flow operators - loops, branches, gates
	controlFlowSteps, err := formula.ApplyControlFlow(resolved.Steps, resolved.Compose)
	if err != nil {
		return nil, fmt.Errorf("applying control flow: %w", err)
	}
	resolved.Steps = controlFlowSteps

	// Apply advice transformations
	if len(resolved.Advice) > 0 {
		resolved.Steps = formula.ApplyAdvice(resolved.Steps, resolved.Advice)
	}

	// Apply inline step expansions
	inlineExpandedSteps, err := formula.ApplyInlineExpansions(resolved.Steps, parser)
	if err != nil {
		return nil, fmt.Errorf("applying inline expansions: %w", err)
	}
	resolved.Steps = inlineExpandedSteps

	// Apply expansion operators
	if resolved.Compose != nil && (len(resolved.Compose.Expand) > 0 || len(resolved.Compose.Map) > 0) {
		expandedSteps, err := formula.ApplyExpansions(resolved.Steps, resolved.Compose, parser)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped error to identify the offending operator (loop/branch/gate) and step id, then fix that construct in the formula file.
  2. Verify every branch/gate target references an existing step id in the same formula.
  3. Validate loop expressions: correct variable name, non-empty collection, correct syntax for the range/foreach form.
  4. Remove or comment out the control-flow block and re-run to isolate which construct is malformed.

Example fix

// before (formula step)
branch: on-fail -> step: "verify-fix"   # step id renamed
// after
branch: on-fail -> step: "verify"       # matches existing step id
Defensive patterns

Strategy: validation

Validate before calling

func controlFlowTargetsExist(steps []*formula.Step) error {
	ids := map[string]bool{}
	for _, s := range steps {
		ids[s.ID] = true
	}
	for _, s := range steps {
		for _, target := range s.ControlFlowTargets() { // branch/gate step references
			if !ids[target] {
				return fmt.Errorf("step %q references unknown step %q", s.ID, target)
			}
		}
	}
	return nil
}

Type guard

func stepExists(steps []*formula.Step, id string) bool {
	for _, s := range steps {
		if s.ID == id {
			return true
		}
	}
	return false
}

Try / catch

steps, err := formula.ApplyControlFlow(resolved.Steps, resolved.Compose)
if err != nil {
	return fmt.Errorf("bad loop/branch/gate in formula %q: %w", formulaName, err)
}

Prevention

When it happens

Trigger: A formula step uses control-flow syntax (foreach/loop, branch/if, gate) and ApplyControlFlow cannot evaluate it: empty or malformed loop collection expression, branch condition that doesn't parse, branch/gate target step id that doesn't exist in the step list.

Common situations: Hand-written loop expressions with wrong variable syntax; a branch referencing a step renamed or removed during editing; a gate condition using a variable not provided to the run; copy-pasting control-flow blocks between formulas without adjusting step ids.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/9ac4b870d465a6a1. Report an issue: GitHub.