gastownhall/beads · warning

empty range expression

Error message

empty range expression

What it means

ParseRange() trims the expression and rejects an empty string outright, because there is no start..end to parse. The range expression (e.g. inside a loop operator) ended up empty after whitespace trimming.

Source

Thrown at internal/formula/range.go:45

// rangePattern matches "start..end" format.
var rangePattern = regexp.MustCompile(`^(.+)\.\.(.+)$`)

// rangeVarPattern matches {varname} placeholders in range expressions.
var rangeVarPattern = regexp.MustCompile(`\{(\w+)\}`)

// ParseRange parses a range expression and evaluates it using the given variables.
// Returns the start and end values of the range.
//
// Examples:
//
//	ParseRange("1..10", nil)           -> {1, 10}
//	ParseRange("1..2^3", nil)          -> {1, 8}
//	ParseRange("1..2^{n}", {"n":"3"})  -> {1, 8}
func ParseRange(expr string, vars map[string]string) (*RangeSpec, error) {
	expr = strings.TrimSpace(expr)
	if expr == "" {
		return nil, fmt.Errorf("empty range expression")
	}

	// 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

View on GitHub (pinned to 71377f2769)

Solutions

  1. Provide a concrete range expression like "1..10" where the loop's range operand is defined.
  2. Check that the variable feeding the range expression is defined in the vars map / frontmatter.
  3. Add a guard that skips the loop when the range operand is empty instead of parsing it.

Example fix

# before: molecule frontmatter
loop:
  range: ""   # empty

# after
loop:
  range: "1..5"
Defensive patterns

Strategy: validation

Validate before calling

expr := strings.TrimSpace(rawRange)
if expr == "" {
	// skip loop or use a default
	rawRange = "1..1"
}

Try / catch

spec, err := ParseRange(expr, vars)
if err != nil {
	if strings.Contains(err.Error(), "empty range expression") {
		// skip iteration set gracefully
	}
}

Prevention

When it happens

Trigger: Calling ParseRange("", vars) or ParseRange(" ", vars); a loop expansion where the range operand is an unbound or empty template variable (e.g. 'for i in {{range}}' with range unset), so expandLoopWithVars receives an empty expression.

Common situations: A loop variable in a molecule left blank or undefined; frontmatter key typo so the intended range value is never picked up; whitespace-only value that looks set but trims to nothing.

Related errors


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