gastownhall/beads · error
evaluating range end %q: %w
Error message
evaluating range end %q: %w
What it means
ParseRange() evaluated the start side fine but EvaluateExpr failed on the end expression, so the end side of the range is not a valid arithmetic expression after variable substitution. The failing end expression and the evaluator's cause are wrapped in the error.
Source
Thrown at internal/formula/range.go:66
// Parse start..end format
m := rangePattern.FindStringSubmatch(expr)
if m == nil {
return nil, fmt.Errorf("invalid range format %q: expected start..end", expr)
}
startExpr := strings.TrimSpace(m[1])
endExpr := strings.TrimSpace(m[2])
// Evaluate start expression
start, err := EvaluateExpr(startExpr, vars)
if err != nil {
return nil, fmt.Errorf("evaluating range start %q: %w", startExpr, err)
}
// Evaluate end expression
end, err := EvaluateExpr(endExpr, vars)
if err != nil {
return nil, fmt.Errorf("evaluating range end %q: %w", endExpr, err)
}
return &RangeSpec{Start: start, End: end}, nil
}
// EvaluateExpr evaluates a mathematical expression with variable substitution.
// Supports: + - * / ^ (power) and parentheses.
// Variables use {name} syntax.
func EvaluateExpr(expr string, vars map[string]string) (int, error) {
// Substitute variables first
expr = substituteVars(expr, vars)
// Tokenize and parse
tokens, err := tokenize(expr)
if err != nil {
return 0, err
}
View on GitHub (pinned to 71377f2769)
Solutions
- Fix the end expression to valid arithmetic, e.g. "1..10" or "1..2^{n}".
- Ensure the variables referenced on the end side are present in the vars map and numeric after substitution.
- Inspect the inner EvaluateExpr error to pinpoint whether it is an unknown variable or invalid token.
Example fix
# before
range: "1..{count}" # count = "auto"
# after
vars: { count: "10" }
range: "1..{count}" Defensive patterns
Strategy: validation
Validate before calling
// Check that every {var} in the end expression exists and is numeric.
for _, m := range varRefRe.FindAllStringSubmatch(endExpr, -1) {
v, ok := vars[m[1]]
if !ok {
return fmt.Errorf"undefined var %q in range end", m[1]
}
if _, err := strconv.Atoi(strings.TrimSpace(v)); err != nil {
return fmt.Errorf"var %q=%q is not numeric", m[1], v
}
} Try / catch
spec, err := ParseRange(expr, vars)
if err != nil {
if strings.Contains(err.Error(), "evaluating range end") {
// fix the end expression or the vars it references
}
} Prevention
- Coerce count-like vars to integers before they are substituted into ranges.
- Reject non-numeric values at config load time for vars used in range ends.
- Cover count-driven loops in tests with both present and absent count vars.
When it happens
Trigger: ParseRange("1..b", vars) with 'b' undefined; end expressions containing unsupported operators or non-numeric residue; unexpanded placeholders like "1..2^{k}" where k is absent from vars; expandLoopWithVars passing a partially-substituted end expression.
Common situations: Count-driven loops ('1..{count}') where the count var was never set or was set to a non-numeric string like 'auto'; typos in the end-side variable name; copy-paste leaving currency symbols or whitespace tokens in the expression.
Related errors
- evaluating range start %q: %w
- loop %q: invalid range %q: %w
- loop %q: %w
- loop %q: range end (%d) is less than start (%d)
- ErrVarValidation
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a698976f24a2fb1a.
Report an issue: GitHub.