{"record":{"id":"e76678f37363389f","repo":"argoproj/argo-workflows","slug":"unable-to-delete-azure-blob-s-w","errorCode":null,"errorMessage":"unable to delete Azure Blob %s: %w","messagePattern":"unable to delete Azure Blob (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/artifacts/azure/azure.go","lineNumber":408,"sourceCode":"\t\t}\n\t}\n\tif directoryFile != \"\" {\n\t\treturn DeleteBlob(ctx, containerClient, directoryFile, true)\n\t}\n\treturn nil\n}\n\nfunc DeleteBlob(ctx context.Context, containerClient *container.Client, blobName string, allowNonExistent bool) error {\n\tblobClient := containerClient.NewBlobClient(blobName)\n\n\t_, err := blobClient.Delete(ctx, nil)\n\tif err != nil {\n\t\tif allowNonExistent && bloberror.HasCode(err, bloberror.BlobNotFound) {\n\t\t\tlogger := logging.RequireLoggerFromContext(ctx)\n\t\t\tlogger.WithField(\"blob\", blobName).WithError(err).Debug(ctx, \"blob to delete does not exist\")\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"unable to delete Azure Blob %s: %w\", blobName, err)\n\t}\n\treturn nil\n}\n\n// ListObjects lists the files in Azure Blob Storage\nfunc (azblobDriver *ArtifactDriver) ListObjects(ctx context.Context, artifact *wfv1.Artifact) ([]string, error) {\n\tvar files []string\n\tlogger := logging.RequireLoggerFromContext(ctx)\n\tlogger.WithField(\"endpoint\", artifact.Azure.Endpoint).\n\t\tWithField(\"container\", artifact.Azure.Container).\n\t\tWithField(\"blob\", artifact.Azure.Blob).\n\t\tInfo(ctx, \"Listing blobs in Azure Blob Storage\")\n\n\tcontainerClient, err := azblobDriver.newAzureContainerClient(ctx)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to create Azure Blob Container client: %w\", err)\n\t}\n","sourceCodeStart":390,"sourceCodeEnd":426,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/artifacts/azure/azure.go#L390-L426","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: hard failure on missing blob\nerr := DeleteBlob(ctx, client, name, false)\n// after: tolerate missing blob\nerr := DeleteBlob(ctx, client, name, true)","handlingStrategy":"type-guard","validationCode":"// check delete permission ahead of time via a harmless probe\nerr := driver.Delete(ctx, testArtifact)\nif err != nil && bloberror.HasCode(err, bloberror.AuthorizationFailure) {\n    return errors.New(\"credential lacks delete permission on container\")\n}","typeGuard":"var respErr *azcore.ResponseError\nif errors.As(err, &respErr) && bloberror.HasCode(err, bloberror.BlobNotFound) {\n    // treat as already-deleted success\n}","tryCatchPattern":"if err := driver.Delete(ctx, artifact); err != nil {\n    var respErr *azcore.ResponseError\n    if errors.As(err, &respErr) && respErr.ErrorCode == string(bloberror.BlobNotFound) {\n        return nil // idempotent delete\n    }\n    return err\n}","preventionTips":["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."],"tags":["azure","blob-storage","delete","permissions"],"backgroundTag":"azure-blob-delete-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"}