If you have ever shipped a service that waited until 2 AM to reveal a missing config value, you know the special kind of adrenaline that only a pager can deliver.

This post shows how to stop silent misconfiguration by validating options up front using IValidateOptions. We will bind strongly typed settings, add cross property rules, inject services into validators, support named options for multiple clients, and fail fast at startup with ValidateOnStart.

The silent failure problem

Binding settings to a class is great, but binding does not imply valid. Missing or out of range values will happily slide through.

Here is a tiny options class we will use in examples.

public sealed class SmtpOptions
{
  public string? Host { get; set; }
  public int Port { get; set; } = 25;
  public bool UseSsl { get; set; }
  public string? Sender { get; set; }
}

And a minimal Program.cs that binds configuration. Nothing here prevents a null Host from sneaking into production.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddOptions<SmtpOptions>()
  .Bind(builder.Configuration.GetSection("Smtp"));

var app = builder.Build();
app.MapGet("/", () => "It boots, but is it valid?");
app.Run();

This article will be available on August 3, 2026 at 8 AM Central Time US