gastownhall/beads · error
applying gates: %w
Error message
applying gates: %w
What it means
ApplyControlFlow wraps failures from applyGatesWithMap with 'applying gates: %w'. Gate rules attach a 'gate:<condition>' label to a target step, evaluated at runtime by the patrol executor. This error means a gate rule is missing 'before' or 'condition', its condition fails ParseCondition syntax validation, or the 'before' target step ID does not exist.
Source
Thrown at internal/formula/controlflow.go:572
// Apply loops first (expands steps) - ApplyLoops already returns new slice
steps, err = ApplyLoops(steps)
if err != nil {
return nil, fmt.Errorf("applying loops: %w", err)
}
// Build stepMap once for branches and gates
// No need to clone here since ApplyLoops already returned a new slice
stepMap := buildStepMap(steps)
// Apply branches (wires dependencies)
if err := applyBranchesWithMap(stepMap, compose); err != nil {
return nil, fmt.Errorf("applying branches: %w", err)
}
// Apply gates (adds labels)
if err := applyGatesWithMap(stepMap, compose); err != nil {
return nil, fmt.Errorf("applying gates: %w", err)
}
return steps, nil
}
// cloneStepDeep creates a deep copy of a step including children.
func cloneStepDeep(s *Step) *Step {
clone := cloneStep(s)
if len(s.Children) > 0 {
clone.Children = make([]*Step, len(s.Children))
for i, child := range s.Children {
clone.Children[i] = cloneStepDeep(child)
}
}
return clone
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped inner error to see which gate rule failed and why (missing field, invalid condition, or unknown target)
- Validate the condition syntax independently with ParseCondition(gate.Condition) and fix the expression
- Confirm the gate's Before step ID exists in the formula, including steps produced by loop expansion
- Correct or remove the invalid gate rule in the compose section
Example fix
// before
gates:
- before: deploy
condition: env ==
// after
gates:
- before: deploy
condition: env == "prod" Defensive patterns
Strategy: validation
Validate before calling
for _, g := range compose.Gate {
if g.Before == "" || g.Condition == "" {
return fmt.Errorf("gate rule requires before and condition")
}
if _, err := ParseCondition(g.Condition); err != nil {
return fmt.Errorf("gate condition %q invalid: %w", g.Condition, err)
}
if _, ok := buildStepMap(steps)[g.Before]; !ok {
return fmt.Errorf("gate target %q not found", g.Before)
}
} Try / catch
out, err := ApplyControlFlow(steps, compose)
if err != nil {
var gateErr error
if strings.Contains(err.Error(), "applying gates") && errors.Unwrap(err) != nil {
gateErr = errors.Unwrap(err)
}
return fmt.Errorf("gate rule rejected: %w", errors.Join(err, gateErr))
} Prevention
- Pre-validate gate conditions with ParseCondition during formula authoring
- Lint gate Before targets against step IDs in CI
- Quote string values inside condition expressions to avoid parse ambiguity
- Re-check gates after any change that renames or expands steps
When it happens
Trigger: Calling ApplyControlFlow(steps, compose) where a compose.Gate entry has an empty Before or Condition, a condition string that ParseCondition rejects, or a Before step ID absent from the step map.
Common situations: Malformed gate condition expressions in formula YAML (bad comparison syntax); gate targeting a step renamed or consumed by a prior expansion; copy-pasted gate rules referencing steps from a different formula.
Related errors
- applying loops: %w
- applying branches: %w
- applying control flow: %w
- applying control flow to %q: %w
- formula %q not accessible: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/68df0b269dd6e9c6.
Report an issue: GitHub.