micro/go-micro · error

verify attempt %d: %w

Error message

verify attempt %d: %w

What it means

This error wraps an error returned by the body step inside the flow.Verify retry loop, annotated with the 1-based attempt number. When the body fails, Verify immediately returns the last successful State wrapped with this message — it does NOT retry on body errors, only on failed grades. The %w wrapping preserves the underlying cause for errors.Is/As.

Source

Thrown at flow/verify.go:90

			return in, fmt.Errorf("flow: Verify requires a grader")
		}
		cur := in
		last := in
		feedback := ""
		for attempt := 1; attempt <= o.MaxAttempts; attempt++ {
			if err := ctx.Err(); err != nil {
				return last, err
			}
			if feedback != "" {
				var err error
				cur, err = stateWithField(cur, o.FeedbackField, feedback)
				if err != nil {
					return last, err
				}
			}
			out, err := body(ctx, cur)
			if err != nil {
				return last, fmt.Errorf("verify attempt %d: %w", attempt, err)
			}
			last = out
			pass, fb, err := grader(ctx, out)
			if err != nil {
				return last, fmt.Errorf("verify grade attempt %d: %w", attempt, err)
			}
			if pass {
				return stateWithVerification(out, true, fb, attempt)
			}
			feedback = fb
			cur = in
			if attempt < o.MaxAttempts && o.Backoff > 0 {
				select {
				case <-time.After(o.Backoff):
				case <-ctx.Done():
					return last, ctx.Err()
				}
			}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Inspect the wrapped cause with errors.Unwrap / errors.Is to find the real body failure.
  2. If the failure is transient and retrying is desired, add retry logic inside the body step itself, since Verify does not retry body errors.
  3. Check that inputs to the body (cur State) are valid; a malformed State will fail every attempt.

Example fix

// before
out, err := body(ctx, cur)
// after (retry transient body errors inside the body)
out, err := retryIfTransient(ctx, cur) // wrap flaky calls with backoff
Defensive patterns

Strategy: try-catch

Try / catch

out, err := step(ctx, in)
if err != nil {
    var cause error
    if errors.As(err, &cause) || errors.Unwrap(err) != nil {
        cause = errors.Unwrap(err)
    }
    if isTransient(cause) {
        // retry inside the body; Verify does not retry body errors
        out, err = step(ctx, in)
    }
    return out, err
}

Prevention

When it happens

Trigger: Any invocation of a Verify-wrapped step where body(ctx, cur) returns a non-nil error on attempt N; message reads 'verify attempt N: <underlying error>'.

Common situations: The body step calls an LLM/API that fails (rate limit, timeout, invalid response); the body panics-free but returns an error on first or later attempts; transient network failures during attempt 1.

Related errors


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