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

  1. Print the end expression after substituteVars to see exactly what the tokenizer rejects.
  2. Fix the end bound to a valid expression (literal integer or valid variable reference).
  3. Ensure the placeholder variable used in the end expression is defined in placeholderVars and substitutes to a non-empty value.
  4. 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

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


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