gastownhall/beads · error
gate: before is required
Error message
gate: before is required
What it means
applyGatesWithMap requires every gate rule to specify a `before` step — the step that gets the gate condition label and is conditionally skipped at runtime. This error is returned when a gate entry in ComposeRules has an empty Before field. The library refuses to apply a gate with no target because the condition would have nothing to attach to.
Source
Thrown at internal/formula/controlflow.go:518
if err := applyGatesWithMap(stepMap, compose); err != nil {
return nil, err
}
return cloned, nil
}
// applyGatesWithMap applies gate rules using a pre-built stepMap.
// This is the internal implementation used by both ApplyGates and ApplyControlFlow.
// The stepMap entries are modified in place.
func applyGatesWithMap(stepMap map[string]*Step, compose *ComposeRules) error {
if compose == nil || len(compose.Gate) == 0 {
return nil
}
for _, gate := range compose.Gate {
// Validate the gate rule
if gate.Before == "" {
return fmt.Errorf("gate: before is required")
}
if gate.Condition == "" {
return fmt.Errorf("gate: condition is required")
}
// Validate the condition syntax
_, err := ParseCondition(gate.Condition)
if err != nil {
return fmt.Errorf("gate: invalid condition %q: %w", gate.Condition, err)
}
// Find the target step
step, ok := stepMap[gate.Before]
if !ok {
return fmt.Errorf("gate: target step %q not found", gate.Before)
}
// Add gate label for runtime evaluation using JSON for unambiguous parsingView on GitHub (pinned to 71377f2769)
Solutions
- Add the `before` field to the gate rule with the ID of the step the gate should guard
- If the gate is unnecessary, remove the empty gate entry from the compose rules
- Check the config file for a blank `before:` key left behind by an edit or merge
Example fix
// before (compose rules)
gate: [{condition: "label:critical"}]
// after
gate: [{before: deploy, condition: "label:critical"}] Defensive patterns
Strategy: validation
Validate before calling
func validateGateRules(compose *ComposeRules) error {
for i, g := range compose.Gate {
if g.Before == "" {
return fmt.Errorf("gate[%d]: missing required field 'before'", i)
}
}
return nil
} Try / catch
if _, err := formula.ApplyGates(steps, compose); err != nil {
if strings.Contains(err.Error(), "gate: before is required") {
return fmt.Errorf("workflow config error: every gate rule needs a 'before' step; check gate entries in compose rules")
}
return err
} Prevention
- Always fill both `before` and `condition` when adding a gate entry
- Use a schema/validator for workflow config that marks gate.before as required
- Never construct GateRule structs without initializing Before
- Review gate blocks after config merges for dropped fields
When it happens
Trigger: Calling ApplyGates or ApplyControlFlow with a ComposeRules whose Gate[i].Before is the empty string — e.g. a gate entry created without the before field, or one unmarshaled from config where `before:` was left blank.
Common situations: YAML/JSON workflow config where the `before:` key under a gate was omitted or left empty after editing; programmatically constructed GateRule structs missing field initialization; merging config files that dropped the field.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- gate: condition is required
- branch: parallel step %q not found
- gate: target step %q not found
- formula %q not accessible: %w
- loop %q: max must be positive
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ef7551e96799c35f.
Report an issue: GitHub.