gastownhall/beads · error
gate: condition is required
Error message
gate: condition is required
What it means
applyGatesWithMap requires every gate rule to carry a non-empty `condition`, which is evaluated at runtime by the patrol executor to decide whether the gated step runs. This error is returned when Gate[i].Condition is empty. A gate without a condition is meaningless, so the library rejects it before adding labels.
Source
Thrown at internal/formula/controlflow.go:521
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 parsing
gateMeta := map[string]string{"condition": gate.Condition}
gateJSON, _ := json.Marshal(gateMeta)
gateLabel := fmt.Sprintf("gate:%s", string(gateJSON))View on GitHub (pinned to 71377f2769)
Solutions
- Add a valid condition expression to the gate rule, e.g. condition: "label:critical" or a field comparison
- If the condition value comes from a template/variable, verify it is non-empty at compose time
- Remove the gate entry entirely if no condition is intended
Example fix
// before (compose rules)
gate: [{before: deploy}]
// after
gate: [{before: deploy, condition: "label:critical"}] Defensive patterns
Strategy: validation
Validate before calling
func validateGateConditions(compose *ComposeRules) error {
for i, g := range compose.Gate {
if g.Condition == "" {
return fmt.Errorf("gate[%d]: missing required field 'condition'", i)
}
}
return nil
} Try / catch
if _, err := formula.ApplyGates(steps, compose); err != nil {
if strings.Contains(err.Error(), "gate: condition is required") {
return fmt.Errorf("workflow config error: gate on %q has no condition; add one or remove the gate", gateTarget(compose))
}
return err
} Prevention
- Never add a gate entry without a condition expression
- If conditions come from templates/variables, validate they are non-empty before compose
- Mark gate.condition required in any config schema or linter
- Delete gate entries entirely instead of leaving them with an empty condition
When it happens
Trigger: Calling ApplyGates or ApplyControlFlow with a ComposeRules whose Gate[i].Condition is the empty string — e.g. `before:` was filled in but `condition:` was omitted, left blank, or set from an empty environment/variable substitution.
Common situations: Workflow config where the `condition:` key was deleted or never written; templated configs where the condition comes from a variable that expanded to empty; partial copy-paste of a gate block.
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: before 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/aee607b313e48a2f.
Report an issue: GitHub.