{"record":{"id":"5efe67b92e9c5733","repo":"argoproj/argo-workflows","slug":"unable-to-upload-stream-to-azure-blob-s-w","errorCode":null,"errorMessage":"unable to upload stream to Azure blob %s: %w","messagePattern":"unable to upload stream to Azure blob (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/azure/azure.go","lineNumber":322,"sourceCode":"\treturn nil\n}\n\n// SaveStream saves an artifact from an io.Reader to Azure Blob Storage\nfunc (azblobDriver *ArtifactDriver) SaveStream(ctx context.Context, reader io.Reader, outputArtifact *wfv1.Artifact) error {\n\tlogger := logging.RequireLoggerFromContext(ctx)\n\tlogger.WithField(\"endpoint\", outputArtifact.Azure.Endpoint).\n\t\tWithField(\"container\", outputArtifact.Azure.Container).\n\t\tWithField(\"blob\", outputArtifact.Azure.Blob).\n\t\tInfo(ctx, \"Streaming to Azure Blob Storage\")\n\n\tcontainerClient, err := azblobDriver.newAzureContainerClient(ctx)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to create Azure Blob Container client for %s: %w\", outputArtifact.Azure.Blob, err)\n\t}\n\n\tblobClient := containerClient.NewBlockBlobClient(outputArtifact.Azure.Blob)\n\tif _, err = blobClient.UploadStream(ctx, reader, nil); err != nil {\n\t\treturn fmt.Errorf(\"unable to upload stream to Azure blob %s: %w\", outputArtifact.Azure.Blob, err)\n\t}\n\treturn nil\n}\n\n// PutFile uploads a file to Azure Blob Storage\nfunc PutFile(ctx context.Context, containerClient *container.Client, blobName, path string) error {\n\tblobClient := containerClient.NewBlockBlobClient(blobName)\n\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to open file %s: %w\", path, err)\n\t}\n\tdefer func() {\n\t\tif closeErr := file.Close(); closeErr != nil {\n\t\t\tlogger := logging.RequireLoggerFromContext(ctx)\n\t\t\tlogger.WithError(closeErr).Warn(ctx, \"unable to close file\")\n\t\t}\n\t}()","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/azure/azure.go#L304-L340","documentation":"SaveStream calls blobClient.UploadStream to write the reader's contents to Azure. If the streaming upload fails (auth, throttling, connection reset mid-stream, invalid blob name), the SDK error is wrapped with this message.","triggerScenarios":"Uploading an io.Reader (e.g. container logs, large artifacts) when the network drops mid-stream, the account is throttled, credentials lack write permission, or the blob name is invalid.","commonSituations":"Streaming very large logs over flaky connections; 429 throttling from heavy artifact traffic; container-level firewall blocking; RBAC/key lacking write on the container.","solutions":["Inspect the wrapped Azure error code (AuthorizationFailure, ServerBusy, etc.) and address it.","Retry the operation; UploadStream errors are often transient network failures.","Confirm write permissions (Storage Blob Data Contributor) for the key/identity.","Check storage account firewall/network rules.","For very large streams, increase timeouts and ensure stable connectivity."],"exampleFix":"// before: no retry around streaming upload\nerr := driver.SaveStream(ctx, reader, artifact)\n// after: retry transient failures\nwait.Backoff(... ) // retry SaveStream on 5xx/timeout errors","handlingStrategy":"retry","validationCode":"if reader == nil {\n  return errors.New(\"nil reader passed to SaveStream\")\n}\nif artifact.Azure.Blob == \"\" {\n  return errors.New(\"blob name is empty\")\n}","typeGuard":"func isRetryableUploadErr(err error) bool {\n  var re *azcore.ResponseError\n  if !errors.As(err, &re) { return false }\n  return re.StatusCode == 429 || re.StatusCode >= 500 || errors.Is(err, io.ErrUnexpectedEOF)\n}","tryCatchPattern":"err := retry.OnError(wait.Backoff{Steps: 4, Duration: time.Second, Factor: 2},\n  isRetryableUploadErr, func() error {\n    return driver.SaveStream(ctx, reader, artifact)\n  })","preventionTips":["Wrap streamed uploads in bounded retries with backoff.","Increase timeouts for very large streams.","Confirm write RBAC/keys before long-running stream jobs.","Watch storage-account throttle metrics (429)."],"tags":["azure","blob-storage","streaming","upload","network"],"backgroundTag":"azure-blob-upload-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"}