{"record":{"id":"fc4465308f6019c4","repo":"gastownhall/beads","slug":"count-comparison-requires-integer-value-got-q","errorCode":null,"errorMessage":"count comparison requires integer value, got %q: %w","messagePattern":"count comparison requires integer value, got %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/formula/condition.go","lineNumber":376,"sourceCode":"\n\tcase \"count\":\n\t\tcount := 0\n\t\tfor _, s := range steps {\n\t\t\t// For steps.complete pattern, field is the status to count\n\t\t\tif c.AggregateOver == \"steps\" && (c.Field == \"complete\" || c.Field == \"failed\" || c.Field == \"pending\" || c.Field == \"in_progress\") {\n\t\t\t\tif s.Status == c.Field {\n\t\t\t\t\tcount++\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsatisfied, _ := matchStep(s, c.Field, OpEqual, c.Value)\n\t\t\t\tif satisfied {\n\t\t\t\t\tcount++\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\texpected, err := strconv.Atoi(c.Value)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"count comparison requires integer value, got %q: %w\", c.Value, err)\n\t\t}\n\t\tsatisfied, reason := compareInt(count, c.Operator, expected)\n\t\treturn &ConditionResult{\n\t\t\tSatisfied: satisfied,\n\t\t\tReason:    reason,\n\t\t}, nil\n\t}\n\n\treturn nil, fmt.Errorf(\"unknown aggregate function: %s\", c.AggregateFunc)\n}\n\nfunc (c *Condition) evaluateExternal(ctx *ConditionContext) (*ConditionResult, error) {\n\tswitch c.ExternalType {\n\tcase \"file.exists\":\n\t\tpath := c.ExternalArg\n\t\t// Substitute variables\n\t\tfor k, v := range ctx.Vars {\n\t\t\tpath = strings.ReplaceAll(path, \"{{\"+k+\"}}\", v)","sourceCodeStart":358,"sourceCodeEnd":394,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/formula/condition.go#L358-L394","documentation":"For a count aggregate (children(x).count(...) or steps.complete N), the comparison value must parse as an integer via strconv.Atoi. The count of matching steps is an int, so a non-numeric expected value cannot be compared and evaluation aborts with this wrapped error.","triggerScenarios":"Evaluate() on a Type=aggregate condition with AggregateFunc=\"count\" whose Value is non-integer — e.g. `children(task).count(status == 'complete') >= three`, or a quoted value like `'3'` that includes stray characters/whitespace.","commonSituations":"Hand-writing the trailing comparison of a count expression with a word instead of a number; variable substitution injecting a non-numeric string; copying a float (3.0) or value with a unit (3x); programmatic construction where Value was populated from the inner condition's quoted string instead of the trailing comparison.","solutions":["Use a plain integer literal in the comparison: `children(task).count(status == 'complete') >= 3`","Strip quotes/whitespace from the value before constructing the Condition.Value field","Parse with strconv.Atoi yourself (or ValidateRange-style check) before calling Evaluate to fail fast with a clearer message"],"exampleFix":"// before\ncond, _ := formula.ParseCondition(\"children(t).count(status == 'complete') >= 'three'\")\nres, err := cond.Evaluate(ctx) // count comparison requires integer value, got \"three\"\n// after\ncond, _ := formula.ParseCondition(\"children(t).count(status == 'complete') >= 3\")\nres, err := cond.Evaluate(ctx)","handlingStrategy":"validation","validationCode":"if _, err := strconv.Atoi(cond.Value); err != nil {\n\treturn fmt.Errorf(\"count condition needs integer value, got %q\", cond.Value)\n}\nres, err := cond.Evaluate(ctx)","typeGuard":"func isIntString(s string) bool { _, err := strconv.Atoi(s); return err == nil }","tryCatchPattern":"res, err := cond.Evaluate(ctx)\nif err != nil && strings.Contains(err.Error(), \"count comparison requires integer value\") {\n\treturn fmt.Errorf(\"fix the count literal in %q\", cond.Raw)\n}\nreturn res, err","preventionTips":["Always write count comparisons with bare integer literals (>= 3, not 'three' or 3.0)","Strip quotes/whitespace from interpolated values before building count conditions","Pre-parse count values with strconv.Atoi at formula-load time"],"tags":["formula","aggregate","integer-parsing"],"backgroundTag":"invalid-numeric-value","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}