dotnet/orleans · error · OrleansConfigurationException

Invalid AdoNetGrainStorageOptions for AdoNetGrainStorage {na

Error message

Invalid AdoNetGrainStorageOptions for AdoNetGrainStorage {name}. Options is required.

What it means

Thrown by the AdoNetGrainStorageOptionsValidator constructor when the configurationOptions argument is null. This is a defensive null-check at validator construction time and indicates the DI container resolved a null AdoNetGrainStorageOptions for the given storage name.

Source

Thrown at src/AdoNet/Orleans.Persistence.AdoNet/Options/AdoNetGrainStorageOptions.cs:88

        public bool DeleteStateOnClear { get; set; }
    }

    /// <summary>
    /// ConfigurationValidator for AdoNetGrainStorageOptions
    /// </summary>
    public class AdoNetGrainStorageOptionsValidator : IConfigurationValidator
    {
        private readonly AdoNetGrainStorageOptions options;
        private readonly string name;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="configurationOptions">The option to be validated.</param>
        /// <param name="name">The name of the option to be validated.</param>
        public AdoNetGrainStorageOptionsValidator(AdoNetGrainStorageOptions configurationOptions, string name)
        {
            this.options = configurationOptions ?? throw new OrleansConfigurationException($"Invalid AdoNetGrainStorageOptions for AdoNetGrainStorage {name}. Options is required.");
            this.name = name;
        }

        /// <inheritdoc cref="IConfigurationValidator"/>
        public void ValidateConfiguration()
        {
            if (string.IsNullOrWhiteSpace(this.options.Invariant))
            {
                throw new OrleansConfigurationException($"Invalid {nameof(AdoNetGrainStorageOptions)} values for {nameof(AdoNetGrainStorage)} \"{name}\". {nameof(options.Invariant)} is required.");
            }

            if (string.IsNullOrWhiteSpace(this.options.ConnectionString) == (this.options.DataSource is null))
            {
                throw new OrleansConfigurationException($"Invalid {nameof(AdoNetGrainStorageOptions)} values for {nameof(AdoNetGrainStorage)} \"{name}\". Configure exactly one of {nameof(options.ConnectionString)} or {nameof(options.DataSource)}.");
            }

            if (this.options.HashPicker == null)
            {

View on GitHub (pinned to fca799fa70)

Solutions

  1. Add a Configure<AdoNetGrainStorageOptions>(name, ...) binding whose name matches the AddAdoNetGrainStorage(name) call.
  2. Use the AddAdoNetGrainStorage(name, configureOptions) overload which binds both registration and options.
  3. Verify the storage name string is identical in AddGrainStorage/AddAdoNetGrainStorage and the options delegate.

Example fix

// before
builder.AddAdoNetGrainStorage("profile"); // no options delegate

// after
builder.AddAdoNetGrainStorage("profile", o =>
{
    o.Invariant = AdoNetInvariants.InvariantNameSqlServer;
    o.ConnectionString = "Server=.;Database=Orleans;";
});
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the named storage options resolve.
var resolved = serviceProvider.GetService<IOptionsMonitor<AdoNetGrainStorageOptions>>()?.Get(name);
if (resolved is null) throw new InvalidOperationException($"AdoNetGrainStorageOptions '{name}' not registered.");

Prevention

When it happens

Trigger: The validator is instantiated (typically by the options/validation infrastructure at host startup) with a null AdoNetGrainStorageOptions. Occurs when AddAdoNetGrainStorage(name) is called without a matching Configure<AdoNetGrainStorageOptions>(name, ...) binding, so DI returns null.

Common situations: Registering named grain storage "profile" but configuring options under a different name or no name; misordered Configure calls; custom DI setup that returns default for the options type.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/565e32a0215b66e9. Report an issue: GitHub.