micro/go-micro · error

loop iteration %d: %w

Error message

loop iteration %d: %w

What it means

The loop's body step returned an error on a given iteration; Loop wraps it with the iteration number for debugging. The wrapped error (%w) is the original body failure — this wrapper only adds context about which iteration failed.

Source

Thrown at flow/loop.go:90

// before the stop condition fires, the loop returns the latest state rather
// than erroring — the guardrail did its job.
func Loop(body StepFunc, opts ...LoopOption) StepFunc {
	o := LoopOptions{Max: 10}
	for _, op := range opts {
		op(&o)
	}
	if o.Max <= 0 {
		o.Max = 10
	}
	return func(ctx context.Context, in State) (State, error) {
		if body == nil {
			return in, fmt.Errorf("flow: Loop requires a body step")
		}
		cur := in
		for iter := 1; iter <= o.Max; iter++ {
			out, err := body(ctx, cur)
			if err != nil {
				return cur, fmt.Errorf("loop iteration %d: %w", iter, err)
			}
			cur = out
			if o.OnIter != nil {
				o.OnIter(iter, cur)
			}
			done, err := loopDone(ctx, o, cur, iter)
			if err != nil {
				return cur, err
			}
			if done {
				return cur, nil
			}
		}
		return cur, nil
	}
}

// loopDone evaluates the stop conditions: a code-defined Until predicate

View on GitHub (pinned to 24529f1404)

Solutions

  1. Unwrap the error (errors.Unwrap / %v of it) to find the root cause inside the body step.
  2. Note the reported iteration number; add logging or an OnIter hook to inspect state at that point.
  3. Lower Loop Max or add a done-condition so the loop exits before failure.
  4. Make the body step idempotent/resilient (retry on transient errors) if it calls external services.

Example fix

// before
out, err := flow.Loop(flow.Max(100))(ctx, in)
// after
out, err := flow.Loop(flow.Max(10), flow.OnIter(func(i int, s flow.State) { log.Printf("iter %d: %v", i, s) }))(ctx, in)
Defensive patterns

Strategy: try-catch

Type guard

func loopIterErr(err error) (int, error) {
	var iter int
	if n, e := fmt.Sscanf(err.Error(), "loop iteration %d:", &iter); n == 1 && e == nil { return iter, errors.Unwrap(err) }
	return 0, err
}

Try / catch

out, err := loopStep(ctx, in)
if err != nil {
	var iterErr *fmt.Errorf
	root := errors.Unwrap(err) // original body failure
	log.Printf("loop failed: iteration context %v, root cause: %v", err, root)
	if ai.ClassifyError(root) == ai.ErrTransient { /* retry the loop */ }
}

Prevention

When it happens

Trigger: Running a Loop where body(ctx, cur) returns a non-nil error at iteration N — could be any failure inside the body step (model call failure, validation error, nested step error).

Common situations: Bodies that call LLMs hitting rate limits mid-loop; body steps failing on state produced by earlier iterations; loops with Max set too high, exhausting a downstream API.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/df9f86f74ef43108. Report an issue: GitHub.