gastownhall/beads · error

unknown condition type: %s

Error message

unknown condition type: %s

What it means

Condition.Evaluate dispatches on the Condition.Type field; if Type is not one of the three supported kinds (field, aggregate, external), evaluation fails with this error. The library only produces a Condition via ParseCondition, which always sets a valid Type, so this only fires when a Condition struct is constructed programmatically with a zero-value or invalid Type.

Source

Thrown at internal/formula/condition.go:241

			Operator: Operator(m[2]),
			Value:    unquote(m[3]),
		}, nil
	}

	return nil, fmt.Errorf("unrecognized condition format: %s", expr)
}

// Evaluate evaluates the condition against the given context.
func (c *Condition) Evaluate(ctx *ConditionContext) (*ConditionResult, error) {
	switch c.Type {
	case ConditionTypeField:
		return c.evaluateField(ctx)
	case ConditionTypeAggregate:
		return c.evaluateAggregate(ctx)
	case ConditionTypeExternal:
		return c.evaluateExternal(ctx)
	default:
		return nil, fmt.Errorf("unknown condition type: %s", c.Type)
	}
}

func (c *Condition) evaluateField(ctx *ConditionContext) (*ConditionResult, error) {
	// Resolve step reference
	stepID := c.StepRef
	if stepID == "step" {
		stepID = ctx.CurrentStep
	}

	step, ok := ctx.Steps[stepID]
	if !ok {
		return &ConditionResult{
			Satisfied: false,
			Reason:    fmt.Sprintf("step %q not found", stepID),
		}, nil
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set Condition.Type explicitly to ConditionTypeField, ConditionTypeAggregate, or ConditionTypeExternal when constructing the struct
  2. Prefer building conditions with formula.ParseCondition(expr), which always assigns a valid Type
  3. Validate Type before calling Evaluate: switch on c.Type and reject anything outside the three constants

Example fix

// before
cond := &formula.Condition{StepRef: "review", Field: "status", Operator: formula.OpEqual, Value: "complete"}
res, err := cond.Evaluate(ctx) // unknown condition type:
// after
cond, err := formula.ParseCondition("review.status == 'complete'")
res, err := cond.Evaluate(ctx)
Defensive patterns

Strategy: validation

Validate before calling

func validConditionType(c *formula.Condition) bool {
	switch c.Type {
	case formula.ConditionTypeField, formula.ConditionTypeAggregate, formula.ConditionTypeExternal:
		return true
	}
	return false
}
if !validConditionType(cond) { return fmt.Errorf("condition type %q not supported", cond.Type) }

Type guard

func isKnownConditionType(t formula.ConditionType) bool {
	return t == formula.ConditionTypeField || t == formula.ConditionTypeAggregate || t == formula.ConditionTypeExternal
}

Try / catch

res, err := cond.Evaluate(ctx)
if err != nil {
	if strings.HasPrefix(err.Error(), "unknown condition type") {
		return fmt.Errorf("condition misconfigured (type=%q): build via formula.ParseCondition", cond.Type)
	}
	return err
}

Prevention

When it happens

Trigger: Calling Condition.Evaluate (or EvaluateCondition on a hand-built Condition) where Condition.Type is "" or an arbitrary string — e.g. `&formula.Condition{Field: "status", Operator: formula.OpEqual, Value: "complete"}` without setting Type.

Common situations: Building a Condition manually instead of via ParseCondition; forgetting to set Type after copying fields; custom code that constructs conditions from config data without mapping the type string to ConditionTypeField/Aggregate/External.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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