{"record":{"id":"b199214cfa4dd62c","repo":"dotnet/orleans","slug":"invalid-nameof-adonetgrainstorageoptions-values-b19921","errorCode":null,"errorMessage":"Invalid {nameof(AdoNetGrainStorageOptions)} values for {nameof(AdoNetGrainStorage)} \"{name}\". Configure exactly one of {nameof(options.ConnectionString)} or {nameof(options.DataSource)}.","messagePattern":"Invalid (.+?) values for (.+?) \"(.+?)\"\\. Configure exactly one of (.+?) or (.+?)\\.","errorType":"validation","errorClass":"OrleansConfigurationException","httpStatus":null,"severity":"error","filePath":"src/AdoNet/Orleans.Persistence.AdoNet/Options/AdoNetGrainStorageOptions.cs","lineNumber":102,"sourceCode":"        /// <param name=\"configurationOptions\">The option to be validated.</param>\n        /// <param name=\"name\">The name of the option to be validated.</param>\n        public AdoNetGrainStorageOptionsValidator(AdoNetGrainStorageOptions configurationOptions, string name)\n        {\n            this.options = configurationOptions ?? throw new OrleansConfigurationException($\"Invalid AdoNetGrainStorageOptions for AdoNetGrainStorage {name}. Options is required.\");\n            this.name = name;\n        }\n\n        /// <inheritdoc cref=\"IConfigurationValidator\"/>\n        public void ValidateConfiguration()\n        {\n            if (string.IsNullOrWhiteSpace(this.options.Invariant))\n            {\n                throw new OrleansConfigurationException($\"Invalid {nameof(AdoNetGrainStorageOptions)} values for {nameof(AdoNetGrainStorage)} \\\"{name}\\\". {nameof(options.Invariant)} is required.\");\n            }\n\n            if (string.IsNullOrWhiteSpace(this.options.ConnectionString) == (this.options.DataSource is null))\n            {\n                throw new OrleansConfigurationException($\"Invalid {nameof(AdoNetGrainStorageOptions)} values for {nameof(AdoNetGrainStorage)} \\\"{name}\\\". Configure exactly one of {nameof(options.ConnectionString)} or {nameof(options.DataSource)}.\");\n            }\n\n            if (this.options.HashPicker == null)\n            {\n                throw new OrleansConfigurationException($\"Invalid {nameof(AdoNetGrainStorageOptions)} values for {nameof(AdoNetGrainStorage)} {name}. {nameof(options.HashPicker)} is required.\");\n            }\n        }\n    }\n\n    /// <summary>\n    /// Provides default configuration HashPicker for AdoNetGrainStorageOptions.\n    /// </summary>\n    public class DefaultAdoNetGrainStorageOptionsHashPickerConfigurator : IPostConfigureOptions<AdoNetGrainStorageOptions>\n    {\n        public void PostConfigure(string? name, AdoNetGrainStorageOptions options)\n        {\n            // preserving explicitly configured HashPicker\n            if (options.HashPicker != null)","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/AdoNet/Orleans.Persistence.AdoNet/Options/AdoNetGrainStorageOptions.cs#L84-L120","documentation":"Thrown by the AdoNetGrainStorageOptionsValidator when both ConnectionString and DataSource are set, or neither is. Grain storage needs exactly one connection source. The equality check `IsNullOrWhiteSpace(ConnectionString) == (DataSource is null)` is true for both unset and both-set.","triggerScenarios":"ValidateConfiguration() runs on AdoNetGrainStorageOptions with neither connection field set, or with both a ConnectionString and a DbDataSource supplied.","commonSituations":"Registering storage with only an Invariant; supplying ConnectionString while also wiring a DbDataSource for connection pooling; partial migration leaving both populated.","solutions":["Set exactly one of options.ConnectionString or options.DataSource for the named storage.","Drop the duplicate if you migrated from ConnectionString to DataSource.","Confirm the appsettings.json storage section contains exactly one connection field."],"exampleFix":"// before\nbuilder.AddAdoNetGrainStorage(\"profile\", o =>\n{\n    o.Invariant = AdoNetInvariants.InvariantNameSqlServer;\n    // no connection -> error\n});\n\n// after\nbuilder.AddAdoNetGrainStorage(\"profile\", o =>\n{\n    o.Invariant = AdoNetInvariants.InvariantNameSqlServer;\n    o.ConnectionString = \"Server=.;Database=Orleans;Trusted_Connection=True;\";\n});","handlingStrategy":"validation","validationCode":"static void CheckStorageConnection(AdoNetGrainStorageOptions o)\n{\n    var exactlyOne = string.IsNullOrWhiteSpace(o.ConnectionString) != (o.DataSource is null);\n    if (!exactlyOne)\n        throw new InvalidOperationException(\"Set exactly one of ConnectionString or DataSource for grain storage.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Standardize on one connection strategy and reuse it across subsystems.","Add a startup assertion for exactly-one connection source per named storage.","Remove the redundant connection field atomically during migration."],"tags":["configuration","adonet","grain-storage","connection-string","startup-validation"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}