gastownhall/beads · error

loop %q: invalid range %q: %w

Error message

loop %q: invalid range %q: %w

What it means

validateLoopSpec validates the loop's Range expression with ValidateRange and wraps any failure. Range loops iterate over a start..end spec; a malformed spec cannot be expanded, so ApplyLoops rejects it up front.

Source

Thrown at internal/formula/controlflow.go:103

	if loop.Count < 0 {
		return fmt.Errorf("loop %q: count must be positive", stepID)
	}

	if loop.Max < 0 {
		return fmt.Errorf("loop %q: max must be positive", stepID)
	}

	// Validate until condition syntax if present
	if loop.Until != "" {
		if _, err := ParseCondition(loop.Until); err != nil {
			return fmt.Errorf("loop %q: invalid until condition %q: %w", stepID, loop.Until, err)
		}
	}

	// Validate range syntax if present
	if loop.Range != "" {
		if err := ValidateRange(loop.Range); err != nil {
			return fmt.Errorf("loop %q: invalid range %q: %w", stepID, loop.Range, err)
		}
	}

	return nil
}

// expandLoop expands a loop step into its constituent steps.
func expandLoop(step *Step) ([]*Step, error) {
	return expandLoopWithVars(step, nil)
}

// expandLoopWithVars expands a loop step using the given variable context.
// The vars map is used to resolve range expressions with variables.
func expandLoopWithVars(step *Step, vars map[string]string) ([]*Step, error) {
	var result []*Step

	if step.Loop.Count > 0 {
		// Fixed-count loop: expand body N times

View on GitHub (pinned to 71377f2769)

Solutions

  1. Fix the range string to match ValidateRange's accepted format (e.g. `start..end`)
  2. Check for typos or extra whitespace/characters in the range value
  3. If the range depends on variables, ensure the vars-expansion path parses it correctly via ParseRange

Example fix

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

Strategy: validation

Validate before calling

func validateLoopRange(r string) error {
	if r == "" {
		return nil
	}
	return formula.ValidateRange(r)
}

Try / catch

steps, err := formula.ApplyLoops(steps)
if err != nil {
	if strings.Contains(err.Error(), "invalid range") {
		return fmt.Errorf("check loop.range syntax (expected start..end): %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: ApplyLoops encountering a LoopSpec whose Range is non-empty but fails ValidateRange (e.g. not of the form 'start..end', non-numeric bounds, reversed bounds at syntax level, extra characters).

Common situations: Writing `range: 1-5` instead of the expected `1..5` separator; leaving spaces or stray characters; unresolved template variables leaving literal `{{x}}` in the range string (use range-with-vars expansion path instead).

Related errors


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