gastownhall/beads · error

gate: invalid condition %q: %w

Error message

gate: invalid condition %q: %w

What it means

Every gate condition must parse as a valid condition expression, so applyGatesWithMap calls ParseCondition on Gate[i].Condition before attaching the gate label. This error wraps the parser's failure — the `%w` verb preserves the underlying parse error (unexpected token, unknown operator, unbalanced quotes, etc.) alongside the offending condition text.

Source

Thrown at internal/formula/controlflow.go:527

// 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))
		step.Labels = appendUnique(step.Labels, gateLabel)
	}

	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped ParseCondition error to find the exact syntax fault and fix the expression in the gate rule
  2. Check the library's condition grammar for supported operators and field names and rewrite the condition accordingly
  3. Quote values containing spaces or special characters as the grammar requires
  4. Test the condition with ParseCondition directly (or a minimal workflow) to iterate quickly

Example fix

// before (compose rules)
gate: [{before: deploy, condition: "label == "}]
// after
gate: [{before: deploy, condition: "label == critical"}]
Defensive patterns

Strategy: validation

Validate before calling

func validateGateConditionSyntax(compose *ComposeRules) error {
	for i, g := range compose.Gate {
		if _, err := formula.ParseCondition(g.Condition); err != nil {
			return fmt.Errorf("gate[%d]: invalid condition %q: %w", i, g.Condition, err)
		}
	}
	return nil
}

Try / catch

if _, err := formula.ApplyGates(steps, compose); err != nil {
	if i := strings.Index(err.Error(), "gate: invalid condition"); i >= 0 {
		return fmt.Errorf("workflow config error: %s (fix the condition expression syntax)", err.Error()[i:])
	}
	return err
}

Prevention

When it happens

Trigger: Calling ApplyGates or ApplyControlFlow with a gate whose Condition string fails ParseCondition — e.g. syntax errors like `label:` with no value, unknown operators, missing operands (`field ==`), or unquoted values containing spaces.

Common situations: Hand-written condition expressions with typos; copying condition syntax from a different tool with an incompatible grammar; quoting problems in YAML that mangle the expression; using operators the condition parser doesn't support.

Related errors


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