microsoft/ailab · error · InvalidOperationException
The storage account connectionstring is not valid.
Error message
The storage account connectionstring is not valid.
What it means
UploadManager.InitializeContainerAsync reads the Azure Blob connection string from configuration (Data:AzureBlobConnection) and calls CloudStorageAccount.Parse during startup; this validation guard fires when that string cannot be parsed into a valid storage account — i.e. the configuration key is missing, empty, or malformed, so no blob container can be initialized for uploads.
Solutions
- Fix the Data:AzureBlobConnection value in appsettings.json/environment to a full 'DefaultEndpointsProtocol=...;AccountName=...;AccountKey=...' connection string
- Use CloudStorageAccount.TryParse and fail fast with a clear startup message when configuration is absent
- Validate configuration at application start (IStartupFilter or options validation) so misconfiguration is caught before uploads are attempted
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at VirtualStage/Speaker.Recorder/Speaker.Recorder/Services/UploadManager.cs:50 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of microsoft/ailab@89fe2fc620 (2026-09-13).
Data as JSON: /api/errors/a2c477ea3da168cd.
Report an issue: GitHub.
Appendix: source
Thrown at VirtualStage/Speaker.Recorder/Speaker.Recorder/Services/UploadManager.cs:50
this.disposeCancellation = new CancellationTokenSource();
this.StorageConnectionString = configuration.GetValue<string>("Data:AzureBlobConnection");
this.GlobalIdentifier = identificationService.GetSanitizedIdentifier();
this.logger = logger;
var connections = configuration.GetValue("Data:DefaultConnectionLimit", Environment.ProcessorCount - 2);
ServicePointManager.DefaultConnectionLimit = Math.Max(connections, 1);
this.uploadRetries = configuration.GetValue("Data:UploadRetries", 10);
this.cloudBlobContainerTask = this.InitializeContainerAsync();
}
private async Task<CloudBlobContainer> InitializeContainerAsync()
{
if (string.IsNullOrEmpty(this.StorageConnectionString) || !CloudStorageAccount.TryParse(this.StorageConnectionString, out var account))
{
this.IsUploadAvailable = false;
this.logger.LogError($"The storage account connectionstring is not valid.");
throw new InvalidOperationException("The storage account connectionstring is not valid.");
}
this.IsUploadAvailable = true;
this.logger.LogInformation($"Initializing Cloud storage for {GlobalIdentifier} in {account.BlobEndpoint}");
CloudBlobClient blobClient = account.CreateCloudBlobClient();
blobClient.DefaultRequestOptions.MaximumExecutionTime = TimeSpan.FromSeconds(10);
blobClient.DefaultRequestOptions.ServerTimeout = TimeSpan.FromSeconds(10);
CloudBlobContainer blobContainer = blobClient.GetContainerReference(GlobalIdentifier);
if (await blobContainer.CreateIfNotExistsAsync().ConfigureAwait(false))
{
this.logger.LogInformation($"The Cloud storage for {GlobalIdentifier} did not exists and was created");
}
return blobContainer;
}
public bool ExistsUploadFile(Session session)
{
var journalFile = new FileInfo(this.GetJournalFileForSession(session.LocalRecordingFolderPath));View on GitHub (pinned to 89fe2fc620)