gastownhall/beads · error
invalid end expression: %w
Error message
invalid end expression: %w
What it means
ValidateRange parses a range expression like {{range i=START..END}} and checks both bound expressions. This error wraps a tokenize() failure on the end (right-hand) expression, meaning the end bound is not syntactically valid token stream. It follows a successful start-expression check, so only the end bound is at fault.
Source
Thrown at internal/formula/range.go:377
// Check that expressions parse (with placeholder vars)
placeholderVars := make(map[string]string)
rangeVarPattern.ReplaceAllStringFunc(expr, func(match string) string {
name := match[1 : len(match)-1]
placeholderVars[name] = "1" // Use 1 as placeholder
return "1"
})
startExpr := strings.TrimSpace(m[1])
startExpr = substituteVars(startExpr, placeholderVars)
if _, err := tokenize(startExpr); err != nil {
return fmt.Errorf("invalid start expression: %w", err)
}
endExpr := strings.TrimSpace(m[2])
endExpr = substituteVars(endExpr, placeholderVars)
if _, err := tokenize(endExpr); err != nil {
return fmt.Errorf("invalid end expression: %w", err)
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Print the end expression after substituteVars to see exactly what the tokenizer rejects.
- Fix the end bound to a valid expression (literal integer or valid variable reference).
- Ensure the placeholder variable used in the end expression is defined in placeholderVars and substitutes to a non-empty value.
- Run tokenize() on the end expression yourself in a quick script to confirm it parses before validating the whole formula.
Example fix
// before
{{range i=0..}}
// after
{{range i=0..9}} Defensive patterns
Strategy: validation
Validate before calling
endExpr := strings.TrimSpace(m[2])
if endExpr == "" {
return fmt.Errorf("range end expression is empty")
}
if _, err := tokenize(endExpr); err != nil {
return fmt.Errorf("range end %q invalid: %v", endExpr, err)
} Try / catch
var verr *ValidationError
if errors.As(err, &verr) && strings.Contains(err.Error(), "invalid end expression") { /* fix formula range syntax */ } Prevention
- Always write explicit, non-empty range ends (e.g. `..9`).
- Check that variables used in range bounds substitute to valid integer strings.
- Lint formula range expressions in CI with ValidateRange before shipping.
When it happens
Trigger: Calling ValidateRange (directly or via validateLoopSpec) with a range spec whose end expression, after variable substitution, fails tokenize(): unbalanced parentheses/braces, stray operators, or an empty end expression.
Common situations: Formula authors typo the range end (e.g. `..}` or `..items]`), reference a variable that substitutes to an empty/invalid string, or use template syntax that the tokenizer does not accept.
Related errors
- parsing formula: %w
- resolving formula: %w
- applying control flow: %w
- applying inline expansions: %w
- applying expansions: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/17bfb806a99a7f5b.
Report an issue: GitHub.