argoproj/argo-workflows · error
unable to delete Azure Blob %s: %w
Error message
unable to delete Azure Blob %s: %w
What it means
DeleteBlob performs blobClient.Delete and returns this error for any failure that is not BlobNotFound (BlobNotFound is swallowed when allowNonExistent=true). Typical causes are HTTP 403 (auth/permissions), 409, lease conflicts, or network errors.
Source
Thrown at workflow/artifacts/azure/azure.go:408
}
}
if directoryFile != "" {
return DeleteBlob(ctx, containerClient, directoryFile, true)
}
return nil
}
func DeleteBlob(ctx context.Context, containerClient *container.Client, blobName string, allowNonExistent bool) error {
blobClient := containerClient.NewBlobClient(blobName)
_, err := blobClient.Delete(ctx, nil)
if err != nil {
if allowNonExistent && bloberror.HasCode(err, bloberror.BlobNotFound) {
logger := logging.RequireLoggerFromContext(ctx)
logger.WithField("blob", blobName).WithError(err).Debug(ctx, "blob to delete does not exist")
return nil
}
return fmt.Errorf("unable to delete Azure Blob %s: %w", blobName, err)
}
return nil
}
// ListObjects lists the files in Azure Blob Storage
func (azblobDriver *ArtifactDriver) ListObjects(ctx context.Context, artifact *wfv1.Artifact) ([]string, error) {
var files []string
logger := logging.RequireLoggerFromContext(ctx)
logger.WithField("endpoint", artifact.Azure.Endpoint).
WithField("container", artifact.Azure.Container).
WithField("blob", artifact.Azure.Blob).
Info(ctx, "Listing blobs in Azure Blob Storage")
containerClient, err := azblobDriver.newAzureContainerClient(ctx)
if err != nil {
return nil, fmt.Errorf("unable to create Azure Blob Container client: %w", err)
}
View on GitHub (pinned to 35bff19146)
Solutions
- Check the wrapped azblob error code: AuthorizationFailure means grant 'Storage Blob Data Contributor' to the identity.
- If the blob is leased or immutable, break the lease / remove immutability policy before deleting.
- Confirm the SAS token has delete (w/d) permission and has not expired.
- If the blob legitimately may not exist, call DeleteBlob with allowNonExistent=true (Delete already does this) so BlobNotFound is ignored.
- Retry on transient network errors; the SDK's default retry policy covers some of this.
Example fix
// before: hard failure on missing blob err := DeleteBlob(ctx, client, name, false) // after: tolerate missing blob err := DeleteBlob(ctx, client, name, true)
Defensive patterns
Strategy: type-guard
Validate before calling
// check delete permission ahead of time via a harmless probe
err := driver.Delete(ctx, testArtifact)
if err != nil && bloberror.HasCode(err, bloberror.AuthorizationFailure) {
return errors.New("credential lacks delete permission on container")
} Type guard
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && bloberror.HasCode(err, bloberror.BlobNotFound) {
// treat as already-deleted success
} Try / catch
if err := driver.Delete(ctx, artifact); err != nil {
var respErr *azcore.ResponseError
if errors.As(err, &respErr) && respErr.ErrorCode == string(bloberror.BlobNotFound) {
return nil // idempotent delete
}
return err
} Prevention
- Grant Storage Blob Data Contributor (delete) to the identity.
- Disable immutability policies/leases on artifact containers.
- Use allowNonExistent=true deletes for idempotency.
- Keep SAS tokens scoped with delete permission and current.
When it happens
Trigger: Deleting a blob that is leased/immutable (immutability policy or legal hold); credentials lacking delete permission (no Storage Blob Data Contributor role); an active snapshot/writes-with-lease; transient network failure; delete called with allowNonExistent=false on a missing blob.
Common situations: Soft-delete/immutable storage policies on the account; SAS token scoped read-only; RBAC role missing delete action; blob name casing mismatch with allowNonExistent=false.
Related errors
- unable to determine if %s is a directory: %w
- unable to list blob %s in Azure Storage: %w
- unable to test if blob %s is a directory: %w
- error listing blobs %s in Azure Blob Storage container: %w
- unable to download blob %s: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/e76678f37363389f.
Report an issue: GitHub.