App-vNext/Polly · error · ValidationException

{PrimaryMessage}\nValidation Errors:\n{error.ErrorMessage}

Error message

{PrimaryMessage}\nValidation Errors:\n{error.ErrorMessage}

What it means

ValidationHelper.ValidateObject runs data-annotations validation on an options object and, on failure, throws a ValidationException whose message is the primary message followed by each ValidationResult.ErrorMessage on its own line. This is the single funnel through which all Polly.Core strategy options are validated at Add*/Build time, so the thrown message is always '{primary}\nValidation Errors:\n{each error}'.

Source

Thrown at src/Polly.Core/Utils/ValidationHelper.cs:51

        var errors = new List<ValidationResult>();

        lock (ValidatorLock)
        {
            valid = Validator.TryValidateObject(context.Instance, new(context.Instance), errors, true);
        }

        if (!valid)
        {
            var stringBuilder = new StringBuilder(context.PrimaryMessage);
            stringBuilder.AppendLine();

            stringBuilder.AppendLine("Validation Errors:");
            foreach (var error in errors)
            {
                stringBuilder.AppendLine(error.ErrorMessage);
            }

            throw new ValidationException(stringBuilder.ToString());
        }
    }
}

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Read each ErrorMessage line in the thrown ValidationException; it names the property and the constraint that failed.
  2. Correct the offending option value to satisfy the annotation (range, required, regex) and rebuild.
  3. Validate options eagerly after configuration binding using the same data-annotations validator, or configure via the DI options-validation pattern.

Example fix

// before
new RetryStrategyOptions { MaxRetryAttempts = -1, Delay = TimeSpan.FromSeconds(-5) };

// after
new RetryStrategyOptions { MaxRetryAttempts = 3, Delay = TimeSpan.FromSeconds(2) };
Defensive patterns

Strategy: validation

Validate before calling

// Validate options eagerly before adding/building:
var ctx = new ValidationContext(options);
var results = new List<ValidationResult>();
if (!Validator.TryValidateObject(options, ctx, results, true)) {
    throw new ValidationException(string.Join("\n", results.Select(r => r.ErrorMessage)));
}

Try / catch

try { builder.AddRetry(retryOptions); }
catch (ValidationException ex) {
    // ex.Message lists each failing property+constraint; fix and retry
}

Prevention

When it happens

Trigger: Configuring any strategy options object with values that violate [Range]/[Required]/[RegularExpression] data annotations (e.g. RetryStrategyOptions.MaxRetryAttempts = -1, TimeoutStrategyOptions.Timeout = negative), then adding the strategy or building the pipeline.

Common situations: Configuration values bound from appsettings without validation; arithmetic that produces out-of-range numbers; copy-pasted options where a field was left at an invalid default; upgrading Polly and hitting newly-added constraints.

Related errors


AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13). Data as JSON: /api/errors/7df528c1b3d0a56a. Report an issue: GitHub.