argoproj/argo-workflows · error
unable to download directory %s: %w
Error message
unable to download directory %s: %w
What it means
Load confirmed the key is a directory and delegated to DownloadDirectory, which lists all blobs under the prefix and downloads each; this error wraps any failure from that process. The cause is in the wrapped error — usually a list failure or a per-file download failure.
Source
Thrown at workflow/artifacts/azure/azure.go:165
return fmt.Errorf("unable to determine if %s is a directory: %w", artifact.Azure.Blob, err)
}
// It's not a directory and the file doesn't exist, Return the original NoSuchKey error.
if !isDir && !isEmptyFile {
return argoerrors.New(argoerrors.CodeNotFound, origErr.Error())
}
// When we tried to download the blob as a file, we created an empty file for the
// blob as a target. We need to delete that empty file so we can re-create as a directory.
err = os.Remove(path)
if err != nil {
return fmt.Errorf("unable to remove attempted file download %s: %w", path, err)
}
// It's a directory, so download all of the files.
err = azblobDriver.DownloadDirectory(ctx, containerClient, artifact, path)
if err != nil {
return fmt.Errorf("unable to download directory %s: %w", artifact.Azure.Blob, err)
}
return nil
}
// DownloadFile downloads a single file from Azure Blob Storage
func DownloadFile(ctx context.Context, containerClient *container.Client, blobName, path string) error {
blobClient := containerClient.NewBlobClient(blobName)
err := os.MkdirAll(filepath.Dir(path), 0755)
if err != nil {
return fmt.Errorf("unable to create dir for file %s: %w", path, err)
}
outFile, err := os.Create(path)
if err != nil {
return fmt.Errorf("unable to create file %s: %w", path, err)
}
defer func() {View on GitHub (pinned to 35bff19146)
Solutions
- Read the nested wrapped error: if 'unable to list blob' fix list permissions; if 'unable to download file' fix that specific blob's access.
- Re-upload the directory artifact — the source may be missing or incomplete.
- Grant Storage Blob Data Reader on the whole container to the credential.
- Retry on transient network errors; consider narrowing the artifact to fewer blobs if large listings time out.
- Verify all child blob names are valid local paths (no characters illegal on the container filesystem).
Example fix
// before: artifact re-uploaded partially, one blob 403s args: [download, dir/] // after: re-save the directory artifact cleanly argo submit --output-artifact 'dir => azure blob=dir/'
Defensive patterns
Strategy: retry
Validate before calling
// verify every child is downloadable before bulk download
files, err := driver.ListObjects(ctx, artifact)
if err != nil { return err }
for _, f := range files {
if _, err := containerClient.NewBlobClient(f).GetProperties(ctx, nil); err != nil { return err }
} Type guard
func isTransientAzureErr(err error) bool {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) {
switch respErr.StatusCode {
case 500, 502, 503, 504:
return true
}
}
return false
} Try / catch
err := driver.Load(ctx, artifact, path)
if err != nil && isTransientAzureErr(err) {
// retry with backoff; SDK already retries per-request, add loop-level retry
} Prevention
- Snapshot directory artifacts (versioned prefixes) so children are immutable during download
- Grant container-wide Storage Blob Data Reader instead of per-blob policies
- Retry workflow runs on transient wrapped errors
- Keep directory artifacts modest in size/child count
When it happens
Trigger: DownloadDirectory fails: ListObjects returns an error (auth/list permission), DownloadFile for any child blob fails (BlobNotFound for missing child, 403, network), or local MkdirAll/download write fails mid-loop.
Common situations: Directory artifact whose prefix contains thousands of blobs and one is deleted/permission-restricted mid-download, SAS token with read but partial permissions, firewall throttling during bulk download.
Related errors
- unable to download file %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/bc22a0fc19b3c329.
Report an issue: GitHub.