{"record":{"id":"67141019f55d7366","repo":"argoproj/argo-workflows","slug":"unable-to-open-stream-for-blob-s-w","errorCode":null,"errorMessage":"unable to open stream for blob %s: %w","messagePattern":"unable to open stream for blob (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/azure/azure.go","lineNumber":256,"sourceCode":"\t\treturn nil, fmt.Errorf(\"unable to create Azure Blob Container client: %w\", err)\n\t}\n\n\tblobClient := containerClient.NewBlockBlobClient(artifact.Azure.Blob)\n\n\t// Attempt the download. If it fails with a BlobNotFound error, or succeeds but with\n\t// a content length of 0, then it could be that we're attempting to stream a directory.\n\t// Check if the blob represents a directory and return an error if so. If not, then\n\t// return either the original BlobNotFound error or the empty file stream.\n\temptyFile := false\n\tresponse, origErr := blobClient.DownloadStream(ctx, nil)\n\tif origErr == nil {\n\t\temptyFile = *response.ContentLength == 0\n\t\t// We have a normal file blob, so just return the response body stream\n\t\tif !emptyFile {\n\t\t\treturn response.Body, nil\n\t\t}\n\t} else if !bloberror.HasCode(origErr, bloberror.BlobNotFound) {\n\t\treturn nil, fmt.Errorf(\"unable to open stream for blob %s: %w\", artifact.Azure.Blob, origErr)\n\t}\n\n\tisDir, err := azblobDriver.IsDirectory(ctx, artifact)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to test if blob %s is a directory: %w\", artifact.Azure.Blob, err)\n\t}\n\tif isDir {\n\t\treturn nil, argoerrors.New(argoerrors.CodeNotImplemented, \"Directory Stream capability currently unimplemented for Azure Blob\")\n\t} else if !emptyFile {\n\t\t// Not a directory (and not successful retrieval of an empty file), so return\n\t\t// the original BlobNotFound error\n\t\treturn nil, fmt.Errorf(\"unable to open blob stream for %s: %w\", artifact.Azure.Blob, origErr)\n\t}\n\n\treturn response.Body, nil\n}\n\n// Save saves an artifact to Azure Blob Storage","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/azure/azure.go#L238-L274","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before: artifact referencing wrong container\nazure:\n  container: artifacs   # typo\n  blob: out.txt\n// after\nazure:\n  container: artifacts\n  blob: out.txt","handlingStrategy":"try-catch","validationCode":"if artifact.Azure == nil || artifact.Azure.Blob == \"\" || artifact.Azure.Container == \"\" {\n  return fmt.Errorf(\"azure artifact misconfigured: missing blob/container\")\n}","typeGuard":"func azureBlobExists(ctx context.Context, c *container.Client, blob string) bool {\n  _, err := c.NewBlockBlobClient(blob).GetProperties(ctx, nil)\n  return !bloberror.HasCode(err, bloberror.BlobNotFound)\n}","tryCatchPattern":"stream, err := driver.OpenStream(ctx, artifact)\nif err != nil {\n  var respErr *azcore.ResponseError\n  if errors.As(err, &respErr) && respErr.StatusCode == 403 {\n    // fix credentials\n  }\n  return fmt.Errorf(\"open azure artifact stream: %w\", err)\n}","preventionTips":["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."],"tags":["azure","blob-storage","artifact","network"],"backgroundTag":"azure-blob-download-failed","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}