argoproj/argo-workflows · error
unable to open stream for blob %s: %w
Error message
unable to open stream for blob %s: %w
What it means
In Argo's Azure artifact driver, OpenStream downloads a blob via DownloadStream. If that call fails with an error that is NOT bloberror.BlobNotFound (e.g. auth failure, container missing, network error), the driver aborts immediately and wraps the original Azure SDK error with this message. It signals the blob download failed for a reason other than 'blob simply does not exist'.
Source
Thrown at workflow/artifacts/azure/azure.go:256
return nil, fmt.Errorf("unable to create Azure Blob Container client: %w", err)
}
blobClient := containerClient.NewBlockBlobClient(artifact.Azure.Blob)
// Attempt the download. If it fails with a BlobNotFound error, or succeeds but with
// a content length of 0, then it could be that we're attempting to stream a directory.
// Check if the blob represents a directory and return an error if so. If not, then
// return either the original BlobNotFound error or the empty file stream.
emptyFile := false
response, origErr := blobClient.DownloadStream(ctx, nil)
if origErr == nil {
emptyFile = *response.ContentLength == 0
// We have a normal file blob, so just return the response body stream
if !emptyFile {
return response.Body, nil
}
} else if !bloberror.HasCode(origErr, bloberror.BlobNotFound) {
return nil, fmt.Errorf("unable to open stream for blob %s: %w", artifact.Azure.Blob, origErr)
}
isDir, err := azblobDriver.IsDirectory(ctx, artifact)
if err != nil {
return nil, fmt.Errorf("unable to test if blob %s is a directory: %w", artifact.Azure.Blob, err)
}
if isDir {
return nil, argoerrors.New(argoerrors.CodeNotImplemented, "Directory Stream capability currently unimplemented for Azure Blob")
} else if !emptyFile {
// Not a directory (and not successful retrieval of an empty file), so return
// the original BlobNotFound error
return nil, fmt.Errorf("unable to open blob stream for %s: %w", artifact.Azure.Blob, origErr)
}
return response.Body, nil
}
// Save saves an artifact to Azure Blob StorageView on GitHub (pinned to 35bff19146)
Solutions
- Inspect the wrapped origErr in the message (e.g. AuthorizationFailure, ContainerNotFound) and fix the underlying Azure credential or resource it names.
- Verify the artifact spec: azure.endpoint, container, and blob names match the actual storage account.
- Confirm the Kubernetes secret holding the Azure credentials exists and the account key is current.
- Check storage-account firewall/network rules allow the argoexec pod's egress.
- Retry if the wrapped error is transient (503 ServerBusy, timeouts).
Example fix
// before: artifact referencing wrong container azure: container: artifacs # typo blob: out.txt // after azure: container: artifacts blob: out.txt
Defensive patterns
Strategy: try-catch
Validate before calling
if artifact.Azure == nil || artifact.Azure.Blob == "" || artifact.Azure.Container == "" {
return fmt.Errorf("azure artifact misconfigured: missing blob/container")
} Type guard
func azureBlobExists(ctx context.Context, c *container.Client, blob string) bool {
_, err := c.NewBlockBlobClient(blob).GetProperties(ctx, nil)
return !bloberror.HasCode(err, bloberror.BlobNotFound)
} Try / catch
stream, err := driver.OpenStream(ctx, artifact)
if err != nil {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && respErr.StatusCode == 403 {
// fix credentials
}
return fmt.Errorf("open azure artifact stream: %w", err)
} Prevention
- Validate azure endpoint/container/blob in artifact specs at submit time (argo lint).
- Keep storage credentials in a Secret and rotate deliberately.
- Monitor for 403/404 from the storage account alerts.
When it happens
Trigger: Calling OpenStream on an Azure artifact when DownloadStream returns a non-BlobNotFound error: bad/missing storage account key or connection string, nonexistent container, wrong endpoint, ADLS authorization errors, throttling, or network timeouts.
Common situations: Misconfigured AZURE_STORAGE_ACCOUNT/ AZURE_STORAGE_CONNECTION_STRING in the artifact repository config; container name typo; account key rotated but workflow still uses old secret; firewall/VNet blocking the storage account.
Related errors
- unable to download blob %s: %w
- unable to test if blob %s is a directory: %w
- unable to open blob stream for %s: %w
- unable to upload directory %s to Azure: %w
- unable to upload file %s to Azure: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/67141019f55d7366.
Report an issue: GitHub.