{"record":{"id":"da5e857cdca99807","repo":"dotnet/orleans","slug":"no-credentials-specified-use-the-azureblobstorage","errorCode":null,"errorMessage":"No credentials specified. Use the AzureBlobStorageOptions.ConfigureBlobServiceClient method to configure the Azure Blob Service client.","messagePattern":"No credentials specified\\. Use the AzureBlobStorageOptions\\.ConfigureBlobServiceClient method to configure the Azure Blob Service client\\.","errorType":"exception","errorClass":"OrleansConfigurationException","httpStatus":null,"severity":"critical","filePath":"src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorageOptions.cs","lineNumber":148,"sourceCode":"        private readonly AzureBlobStorageOptions options;\n        private readonly string name;\n\n        /// <summary>\n        /// Constructor\n        /// </summary>\n        /// <param name=\"options\">The option to be validated.</param>\n        /// <param name=\"name\">The option name to be validated.</param>\n        public AzureBlobStorageOptionsValidator(AzureBlobStorageOptions options, string name)\n        {\n            this.options = options;\n            this.name = name;\n        }\n\n        public void ValidateConfiguration()\n        {\n            if (this.options.CreateClient is null)\n            {\n                throw new OrleansConfigurationException($\"No credentials specified. Use the {options.GetType().Name}.{nameof(AzureBlobStorageOptions.ConfigureBlobServiceClient)} method to configure the Azure Blob Service client.\");\n            }\n\n            try\n            {\n                AzureBlobUtils.ValidateContainerName(options.ContainerName);\n                AzureBlobUtils.ValidateBlobName(this.name);\n            }\n            catch (ArgumentException e)\n            {\n                throw new OrleansConfigurationException(\n                    $\"Configuration for AzureBlobStorageOptions {name} is invalid. {nameof(this.options.ContainerName)} is not valid\", e);\n            }\n        }\n    }\n}\n","sourceCodeStart":130,"sourceCodeEnd":164,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Persistence.AzureStorage/Providers/Storage/AzureBlobStorageOptions.cs#L130-L164","documentation":"Thrown by AzureBlobStorageOptionsValidator.ValidateConfiguration() when AzureBlobStorageOptions.CreateClient is null. This is the same credential check as the Init() path (error 240) but fires earlier — during Orleans IConfigurationValidator validation, before the provider's Init method runs. It is a fail-fast guard that surfaces missing credentials during configuration validation rather than at lifecycle initialization.","triggerScenarios":"Fires when the Orleans hosting infrastructure invokes ValidateConfiguration() on the AzureBlobStorageOptionsValidator, typically during silo build/start. Occurs when CreateClient is null because no ConfigureBlobServiceClient overload or BlobServiceClient property assignment was made.","commonSituations":"Same root cause as 240 — missing credentials — but caught at validation time. Common when a developer wires up the storage provider but the configuration callback that sets credentials is conditional or skipped (e.g., environment-specific config not loaded in a test environment).","solutions":["Set BlobServiceClient or call ConfigureBlobServiceClient inside the AddAzureBlobGrainStorage options delegate.","Ensure any conditional configuration logic (e.g., if/else by environment) always sets credentials in all branches.","Register an IValidateOptions<AzureBlobStorageOptions> or rely on the built-in validator to fail early in CI.","Move the connection string into IConfiguration and read it in the configure callback so a missing value is caught immediately."],"exampleFix":"// before\nsiloBuilder.AddAzureBlobGrainStorage(\"grainStore\" /* no options delegate */);\n\n// after\nsiloBuilder.AddAzureBlobGrainStorage(\"grainStore\", o =>\n{\n    o.BlobServiceClient = new BlobServiceClient(configuration.GetConnectionString(\"AzureStorage\"));\n});","handlingStrategy":"validation","validationCode":"// Register a custom IValidateOptions to catch this at configuration time\npublic class ValidateAzureBlobOptions : IValidateOptions<AzureBlobStorageOptions>\n{\n    public ValidateOptionsResult Validate(string name, AzureBlobStorageOptions options)\n    {\n        if (options.CreateClient is null && options.BlobServiceClient is null)\n            return ValidateOptionsResult.Fail(\"No BlobServiceClient configured for AzureBlobStorageOptions.\");\n        return ValidateOptionsResult.Success;\n    }\n}","typeGuard":null,"tryCatchPattern":"try { await host.StartAsync(ct); }\ncatch (OrleansConfigurationException ex) when (ex.Message.Contains(\"No credentials specified\"))\n{\n    logger.LogCritical(\"Azure Blob Storage credentials missing — check configuration.\");\n    throw;\n}","preventionTips":["Register IValidateOptions<AzureBlobStorageOptions> to fail fast at configuration time.","Ensure all environment branches (dev/staging/prod) set credentials.","Use connection string validation in startup health checks.","Prefer setting BlobServiceClient directly over the obsolete ConfigureBlobServiceClient."],"tags":["azure","blob-storage","configuration","credentials","validation","orleans"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}