apache/druid · error · IOException

Failed to fetch google cloud storage object from bucket [%s]

Error message

Failed to fetch google cloud storage object from bucket [%s] and prefix [%s].

What it means

GoogleStorage.list() performs a paged blob listing for a bucket+prefix. Although GCS list calls normally return an empty page instead of null, Druid defensively throws this IOException when the SDK returns a null Page, so callers never dereference a missing result. It indicates the listing request failed rather than 'no results'.

Source

Thrown at extensions-core/google-extensions/src/main/java/org/apache/druid/storage/google/GoogleStorage.java:271

  {
    List<Storage.BlobListOption> options = new ArrayList<>();

    if (prefix != null) {
      options.add(Storage.BlobListOption.prefix(prefix));
    }

    if (pageSize != null) {
      options.add(Storage.BlobListOption.pageSize(pageSize));
    }

    if (pageToken != null) {
      options.add(Storage.BlobListOption.pageToken(pageToken));
    }

    Page<Blob> blobPage = storage.get().list(bucket, options.toArray(new Storage.BlobListOption[0]));

    if (blobPage == null) {
      throw new IOE("Failed to fetch google cloud storage object from bucket [%s] and prefix [%s].", bucket, prefix);
    }


    List<GoogleStorageObjectMetadata> googleStorageObjectMetadataList =
        blobPage.streamValues()
                .map(blob -> new GoogleStorageObjectMetadata(
                    blob.getBucket(),
                    blob.getName(),
                    blob.getSize(),
                    blob.getUpdateTimeOffsetDateTime()
                        .toEpochSecond() * 1000
                ))
                .collect(Collectors.toList());

    return new GoogleStorageObjectPage(googleStorageObjectMetadataList, blobPage.getNextPageToken());

  }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Retry the list call; null pages are usually transient client failures.
  2. Validate the bucket name against the project (gsutil ls or console) before listing.
  3. Catch IOException and fall back to an empty metadata list if 'no objects' is an acceptable outcome.
  4. Upgrade/inspect the google-cloud-storage client version if null pages recur with healthy buckets.
  5. Enable client logging to distinguish auth vs transport causes.

Example fix

// before
List<GoogleStorageObjectMetadata> objs = googleStorage.list(bucket, prefix, limit);
// after
List<GoogleStorageObjectMetadata> objs;
try {
  objs = googleStorage.list(bucket, prefix, limit);
} catch (IOException e) {
  log.warn("GCS list failed for gs://%s/%s, treating as empty", bucket, prefix, e);
  objs = Collections.emptyList();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (bucket == null || bucket.isEmpty() || prefix == null) {
  throw new IllegalArgumentException("bucket and prefix required before GCS list");
}

Try / catch

try { page = googleStorage.list(bucket, prefix, limit); }
catch (IOException e) { page = Collections.emptyList(); /* or retry */ }

Prevention

When it happens

Trigger: Calling GoogleStorage.list(bucket, prefix, maxResults) when the Storage client returns a null Page — typically due to a client/transport problem, an invalid bucket argument, or a mocked/failed response in tests.

Common situations: Misspelled or renamed bucket in task-log/output config; transient GCS client failures; unit tests (expectListObjectsPageRequest) simulating null pages; network interruptions mid-list.

Understand the failure class

Background: "empty response", "returned no data", "empty embeddings": what HTTP 200-with-empty-body errors mean across libraries — this error's family across 36 libraries.

Related errors


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