microsoft/ailab · error · InvalidOperationException

blobClient is null

Error message

blobClient is null

What it means

SaveResults(IList<PredictedObject>, string) writes each predicted object's sliced image to Azure Blob Storage using the injected CloudBlobClient. If that client was never initialized (null), no blob operations are possible, so the method throws InvalidOperationException('blobClient is null') before doing any work.

Solutions

  1. Ensure ObjectDetectionAppService is constructed/initialized with a valid CloudBlobClient (pass the Azure Storage connection string)
  2. Check the storage connection string configuration value is present and valid
  3. Construct the service via the factory/DI path used by Run rather than new ObjectDetectionAppService() with defaults
  4. Null-check _cloudBlobClient at construction time and fail fast with a clear configuration error

Example fix

// before
var service = new ObjectDetectionAppService();
await service.SaveResults(objects, id);
// after
var service = ObjectDetectionAppService.Create(storageConnectionString);
await service.SaveResults(objects, id);
Defensive patterns

Strategy: try-catch

Validate before calling

if (service.BlobClient == null)
    throw new InvalidOperationException("ObjectDetectionAppService not initialized with a CloudBlobClient");

Try / catch

try
{
    await service.SaveResults(predictedObjects, id);
}
catch (InvalidOperationException ex) when (ex.Message == "blobClient is null")
{
    logger.LogError(ex, "Blob storage client not initialized; check storage connection string");
    throw;
}

Prevention

When it happens

Trigger: Invoking Run/saveResults on an ObjectDetectionAppService instance whose _cloudBlobClient field was never assigned — e.g. constructed without the blob connection string or a failed initialization path.

Common situations: Missing Azure Storage connection string in config so the factory method never creates the client; constructing the service manually instead of via DI/factory; initialization step skipped in a new hosting path.

Related errors


AI-assisted analysis of microsoft/ailab@89fe2fc620 (2026-09-13). Data as JSON: /api/errors/ed1334f9c57bbc3f. Report an issue: GitHub.

Appendix: source

Thrown at Sketch2Code/Sketch2Code.Core/Services/ObjectDetectionAppService.cs:200

            using (var ms = new MemoryStream(data))
            {
                img = Image.FromStream(ms);

                imageWidth = img.Width;
                imageHeight = img.Height;

                if ((imageWidth == 0) || (imageHeight == 0))
                {
                    throw new InvalidOperationException("Invalid image dimensions");
                }
            }

            return img;
        }

        public async Task SaveResults(IList<PredictedObject> predictedObjects, string id)
        {
            if (_cloudBlobClient == null) throw new InvalidOperationException("blobClient is null");
            var slices_container = $"{id}/slices";

            for (int i = 0; i < predictedObjects.Count; i++)
            {
                PredictedObject result = (PredictedObject)predictedObjects[i];
                await this.SaveResults(result.SlicedImage, slices_container, $"{result.Name}.png");
            }
        }
        public async Task SaveResults(byte[] file, string container, string fileName)
        {
            CloudBlobContainer theContainer = null;

            if (_cloudBlobClient == null) throw new InvalidOperationException("blobClient is null");

            var segments = container.Split(@"/".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            var rootContainerPath = segments.First();

View on GitHub (pinned to 89fe2fc620)