argoproj/argo-workflows · error
unable to download file %s: %w
Error message
unable to download file %s: %w
What it means
While downloading a directory artifact, each child blob is fetched with DownloadFile into its mapped local path; this error wraps the failure of one specific child download. It is the per-file counterpart of the directory download — the nested error carries the actual cause (Azure-side or local FS).
Source
Thrown at workflow/artifacts/azure/azure.go:223
}
err = os.MkdirAll(path, 0755)
if err != nil {
return fmt.Errorf("unable to create local directory %s: %w", path, err)
}
for _, file := range files {
// For ADLS Gen 2 accounts, we'll see a file whose name matches the directory. Skip it.
if file == artifact.Azure.Blob {
continue
}
relKeyPath := strings.TrimPrefix(file, artifact.Azure.Blob)
localPath := filepath.Join(path, relKeyPath)
err = DownloadFile(ctx, containerClient, file, localPath)
if err != nil {
return fmt.Errorf("unable to download file %s: %w", localPath, err)
}
}
return nil
}
// OpenStream opens a stream reader for an artifact from Azure Blob Storage
func (azblobDriver *ArtifactDriver) OpenStream(ctx context.Context, artifact *wfv1.Artifact) (io.ReadCloser, error) {
logger := logging.RequireLoggerFromContext(ctx)
logger.WithField("endpoint", artifact.Azure.Endpoint).
WithField("container", artifact.Azure.Container).
WithField("blob", artifact.Azure.Blob).
Info(ctx, "Streaming from Azure Blob Storage")
containerClient, err := azblobDriver.newAzureContainerClient(ctx)
if err != nil {
return nil, fmt.Errorf("unable to create Azure Blob Container client: %w", err)
}
blobClient := containerClient.NewBlockBlobClient(artifact.Azure.Blob)View on GitHub (pinned to 35bff19146)
Solutions
- Read the nested wrapped error: Azure code => fix access/re-upload that blob; os error => fix local path/permissions/disk.
- Re-upload the directory artifact to ensure all children exist and are consistent.
- If a blob name contains path-hostile characters, sanitize names when saving the artifact.
- Increase disk/emptyDir size if ENOSPC occurred mid-download.
- Retry the workflow — mid-download transient network failures are often one-shot.
Example fix
// before: producer deletes blobs during download step writes output -> workflow downloads same prefix concurrently // after: snapshot first (copy or version prefix) upload to blob: outputs/run-42/ then download outputs/run-42/
Defensive patterns
Strategy: retry
Validate before calling
// check disk headroom before bulk download
var st syscall.Statfs_t
if err := syscall.Statfs(filepath.Dir(path), &st); err == nil {
avail := int64(st.Bavail) * int64(st.Bsize)
if avail < minRequiredBytes { return fmt.Errorf("insufficient disk: %d", avail) }
} Type guard
func isRetryableDownloadErr(err error) bool {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) {
return respErr.StatusCode == 500 || respErr.StatusCode == 503 || respErr.StatusCode == 504
}
return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, io.ErrUnexpectedEOF)
} Try / catch
err := driver.Load(ctx, artifact, path)
if err != nil {
if isRetryableDownloadErr(err) {
time.Sleep(backoff)
err = driver.Load(ctx, artifact, path)
}
} Prevention
- Freeze the source prefix (versioned directories) before downloading
- Provision adequate emptyDir/PVC size for directory artifacts
- Sanitize blob names when saving so derived local paths are valid
- Retry transient errors; investigate nested errors otherwise
When it happens
Trigger: DownloadFile(childBlob, localPath) fails: child blob deleted between list and download (BlobNotFound), 403 on that blob, transient network failure mid-stream, or local os.Create/MkdirAll failure at the derived localPath (permissions, disk full, illegal filename from blob name).
Common situations: Blob names with characters invalid on Linux paths in directory artifacts, concurrent producer writing/deleting blobs while the workflow downloads, ephemeral disk filling during large directory downloads, RBAC that allows some blobs but not others (per-path policies in ADLS Gen2).
Related errors
- unable to download directory %s: %w
- unable to download blob %s: %w
- unable to determine if %s is a directory: %w
- unable to list blob %s in Azure Storage: %w
- unable to open stream for blob %s: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/16c3d0e3c69abc2e.
Report an issue: GitHub.