apache/beam · error · IOException

delete does not delete containers.

Error message

delete does not delete containers.

What it means

delete() refuses to delete anything whose resourceId has no blob component, i.e. an azfs container root. Containers cannot be removed through this filesystem API (it handles virtual folders and blobs only), so it throws an IOException with this message. This prevents users from accidentally wiping a whole container via the generic delete API.

Solutions

  1. Remove the container with the Azure SDK directly: blobContainerClient.delete() or 'az storage container delete'.
  2. Adjust the path list to only include actual blobs / virtual directories (skip container roots).
  3. Use a glob match (azfs://container/**) and delete only matched leaf blobs.
  4. Add a guard in your cleanup loop that skips resources where getBlob() == null.

Example fix

// before
FileSystems.delete(ImmutableList.of(FileSystems.matchNewResource("azfs://mycontainer", false))); // throws
// after
// delete contents via glob, or drop the container with the Azure SDK
MatchResult all = FileSystems.match("azfs://mycontainer/**");
FileSystems.delete(all.metadata().stream().map(MatchResult.Metadata::resourceId).collect(ImmutableList.toImmutableList()));
Defensive patterns

Strategy: validation

Validate before calling

// skip container-root resources before delete
List<ResourceId> deletable = resourceIds.stream()
    .filter(id -> !id.toString().matches("azfs://[^/]+/?"))
    .collect(Collectors.toList());
FileSystems.delete(deletable);

Try / catch

try {
  FileSystems.delete(ids);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().contains("does not delete containers")) {
    // drop container via Azure SDK: containerClient.delete();
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling FileSystems.delete() with an AzfsResourceId whose getBlob() is null — typically a path like azfs://container or azfs://container/ that resolves to the container itself.

Common situations: Cleanup code that deletes directories recursively and reaches the container root; constructing resource IDs from parsed URIs that lack a blob path; users expecting container deletion like the Azure SDK's deleteContainer().

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/426426195fe2f712. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/azure/src/main/java/org/apache/beam/sdk/io/azure/blobstore/AzureBlobStoreFileSystem.java:412

  @Override
  protected void rename(
      List<AzfsResourceId> srcResourceIds,
      List<AzfsResourceId> destResourceIds,
      MoveOptions... moveOptions)
      throws IOException {
    if (moveOptions.length > 0) {
      throw new UnsupportedOperationException("Support for move options is not yet implemented.");
    }
    copy(srcResourceIds, destResourceIds);
    delete(srcResourceIds);
  }

  /** This method will delete a virtual folder or a blob, not a container. */
  @Override
  protected void delete(Collection<AzfsResourceId> resourceIds) throws IOException {
    for (AzfsResourceId resourceId : resourceIds) {
      if (resourceId.getBlob() == null) {
        throw new IOException("delete does not delete containers.");
      }

      BlobContainerClient container =
          client.get().getBlobContainerClient(resourceId.getContainer());

      // deleting a blob that is not a directory
      if (!resourceId.isDirectory()) {
        BlobClient blob = container.getBlobClient(resourceId.getBlob());
        if (!blob.exists()) {
          throw new FileNotFoundException("The resource to delete does not exist.");
        }
        blob.delete();
      }

      // deleting a directory (not a container)
      else {
        PagedIterable<BlobItem> blobsInDirectory =
            container.listBlobsByHierarchy(resourceId.getBlob());

View on GitHub (pinned to 12126d8942)