gastownhall/beads · error

unknown aggregate function: %s

Error message

unknown aggregate function: %s

What it means

evaluateAggregate supports exactly three aggregate functions: all, any, and count. If Condition.AggregateFunc holds anything else, evaluation falls through the switch and returns this error. ParseCondition only emits these three names, so this arises from programmatically built conditions.

Source

Thrown at internal/formula/condition.go:385

			} else {
				satisfied, _ := matchStep(s, c.Field, OpEqual, c.Value)
				if satisfied {
					count++
				}
			}
		}
		expected, err := strconv.Atoi(c.Value)
		if err != nil {
			return nil, fmt.Errorf("count comparison requires integer value, got %q: %w", c.Value, err)
		}
		satisfied, reason := compareInt(count, c.Operator, expected)
		return &ConditionResult{
			Satisfied: satisfied,
			Reason:    reason,
		}, nil
	}

	return nil, fmt.Errorf("unknown aggregate function: %s", c.AggregateFunc)
}

func (c *Condition) evaluateExternal(ctx *ConditionContext) (*ConditionResult, error) {
	switch c.ExternalType {
	case "file.exists":
		path := c.ExternalArg
		// Substitute variables
		for k, v := range ctx.Vars {
			path = strings.ReplaceAll(path, "{{"+k+"}}", v)
		}
		_, err := os.Stat(path)
		exists := err == nil
		return &ConditionResult{
			Satisfied: exists,
			Reason:    fmt.Sprintf("file %q exists: %v", path, exists),
		}, nil

	case "env":

View on GitHub (pinned to 71377f2769)

Solutions

  1. Set AggregateFunc to one of "all", "any", or "count" when building the Condition
  2. Construct aggregates via formula.ParseCondition("children(x).all(status == 'complete')") instead of struct literals
  3. Whitelist-validate the function name before calling Evaluate

Example fix

// before
cond := &formula.Condition{Type: formula.ConditionTypeAggregate, AggregateFunc: "sum", ...}
res, err := cond.Evaluate(ctx) // unknown aggregate function: sum
// after
cond := &formula.Condition{Type: formula.ConditionTypeAggregate, AggregateFunc: "count", ...}
res, err := cond.Evaluate(ctx)
Defensive patterns

Strategy: validation

Validate before calling

func validAggFunc(f string) bool { return f == "all" || f == "any" || f == "count" }
if cond.Type == formula.ConditionTypeAggregate && !validAggFunc(cond.AggregateFunc) {
	return fmt.Errorf("aggregate func %q must be all|any|count", cond.AggregateFunc)
}

Type guard

func isKnownAggregateFunc(f string) bool {
	return f == "all" || f == "any" || f == "count"
}

Try / catch

res, err := cond.Evaluate(ctx)
if err != nil && strings.HasPrefix(err.Error(), "unknown aggregate function") {
	return fmt.Errorf("unsupported aggregate %q; allowed: all, any, count", cond.AggregateFunc)
}
return res, err

Prevention

When it happens

Trigger: Evaluate() on a Type=aggregate Condition whose AggregateFunc is empty or set to a non-supported value (e.g. "none", "sum", "every") when constructed manually or copied from config.

Common situations: Mapping a custom formula DSL to formula.Condition and forgetting a translation for the aggregate verb; zero-value struct construction without setting AggregateFunc; renaming an aggregate function in downstream code without updating all writers.

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/dc22d47d1678536a. Report an issue: GitHub.