apache/druid · info

No files were deleted on the following Azure path: [%s]

Error message

No files were deleted on the following Azure path: [%s]

What it means

AzureStorage.emptyCloudBlobDirectory() lists and deletes blobs under a given prefix and returns the list of deleted files. When nothing was deleted it logs this warning before returning the empty list — it does not throw. The warning helps distinguish 'nothing existed to delete' from a silent no-op during directory cleanup.

Source

Thrown at extensions-core/azure-extensions/src/main/java/org/apache/druid/storage/azure/AzureStorage.java:130

    // https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-list The new client uses flat listing by default.
    final PagedIterable<BlobItem> blobItems = blobContainerClient.listBlobs(
        new ListBlobsOptions().setPrefix(prefix),
        Duration.ofMillis(DELTA_BACKOFF_MS)
    );

    final List<String> deletedFiles = new ArrayList<>();
    blobItems.iterableByPage().forEach(
        page -> page.getElements().forEach(
            blob -> {
              if (blobContainerClient.getBlobClient(blob.getName()).deleteIfExists()) {
                deletedFiles.add(blob.getName());
              }
            }
        )
    );

    if (deletedFiles.isEmpty()) {
      LOG.warn("No files were deleted on the following Azure path: [%s]", prefix);
    }

    return deletedFiles;
  }

  /**
   * Creates and opens an output stream to write data to the block blob.
   * <p>
   * If the blob already exists, an exception will be thrown.
   *
   * @param containerName The name of the storage container.
   * @param blobName      The name of the blob within the container.
   * @param blockSize     (Optional) The block size to use when writing the blob.
   *                      If null, the default block size will be used.
   * @param maxAttempts   (Optional) The maximum number of attempts to retry the upload in case of failure.
   *                      If null, the default value from the system configuration (`druid.azure.maxTries`) will be used.
   *
   * @return An OutputStream for writing the blob.

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Verify the prefix path is correct (datasource/interval formatting) before calling delete/kill
  2. Treat the empty return list as an idempotent no-op if the directory was already expected to be empty
  3. List the container/prefix with a storage explorer to confirm whether blobs ever existed
  4. If the path should exist, check for concurrent kill/cleanup tasks racing with this operation
  5. Silence/expect this warning for kill operations on datasources with no segments
Defensive patterns

Strategy: validation

Validate before calling

// confirm the prefix exists before treating empty deletion as an error
boolean hasBlobs = !storage.listPrefix(container, prefix).isEmpty();

Try / catch

List<String> deleted = storage.emptyCloudBlobDirectory(container, prefix);
if (deleted.isEmpty()) {
  LOG.info("Nothing deleted for %s — already empty or wrong prefix", prefix);
}

Prevention

When it happens

Trigger: Calling emptyCloudBlobDirectory (or deleteObjectsInPath that wraps it) with a prefix under which no blobs exist, or none could be deleted (e.g., already gone).

Common situations: Deleting a segment directory that was already removed; typo in the prefix (wrong datasource/interval path); a concurrent kill task already deleted the blobs; drained or newly created datasources.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/0b752fa5900de68b. Report an issue: GitHub.