quickwit-oss/quickwit · error · StorageError

listing objects is not supported for storage

Error message

listing objects is not supported for storage `{}`

What it means

The `Storage` trait's default `list` implementation returns a stream containing a single Internal error stating that listing is not supported for that storage type. Storages that cannot enumerate objects (historically e.g. certain specialized backends) inherit this default instead of overriding it.

Solutions

  1. Use a storage backend that implements `list` (local FS, S3-compatible, RAM) for listing-dependent operations
  2. If you own the storage implementation, override `fn list(&self, prefix) -> ListObjectsStream` to stream real objects
  3. Restructure the calling code to avoid prefix listing when the backend cannot enumerate (track object paths explicitly)
  4. Treat the StorageErrorKind::Internal from the default method as an unsupported-operation signal in generic code

Example fix

// before (custom storage missing list)
impl Storage for MyStorage { /* no list() */ }
// after
fn list(&self, prefix: &Path) -> ListObjectsStream {
    stream::iter(self.entries.keys().filter(...).cloned().map(Ok)).boxed()
}
Defensive patterns

Strategy: type-guard

Validate before calling

// probe support before bulk operations
match storage.list(&probe_prefix).try_next().await {
    Err(e) if e.kind() == StorageErrorKind::Internal => fallback_to_no_listing(),
    _ => proceed_with_listing(),
}

Try / catch

match storage.list(&prefix).try_collect::<Vec<_>>().await {
    Ok(objs) => use(objs),
    Err(e) if e.kind() == StorageErrorKind::Internal => fallback_no_listing_backend(),
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling `Storage::list` (or anything built on it: delete with prefix, garbage collection, merge listing) on a storage implementation that does not override the default `list` method.

Common situations: Using a custom or minimal Storage implementation in tests/tools that never implemented listing; invoking garbage-collection or bulk-delete flows against such a storage; writing generic code that assumes all storages support listing.

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 quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/b016b8f5029562c4. Report an issue: GitHub.

Appendix: source

Thrown at quickwit/quickwit-storage/src/storage.rs:152

    async fn get_all(&self, path: &Path) -> StorageResult<OwnedBytes>;

    /// Deletes a file.
    ///
    /// This method should return Ok(()) if the file did not exist.
    async fn delete(&self, path: &Path) -> StorageResult<()>;

    /// Deletes multiple files at once.
    ///
    /// The implementation may call `[`Storage::delete`] in a loop if the underlying storage does
    /// not support deleting objects in bulk. The request can fail partially, i.e. some objects are
    /// successfully deleted while others are not.
    async fn bulk_delete<'a>(&self, paths: &[&'a Path]) -> Result<(), BulkDeleteError>;

    /// Lists object metadata for objects whose paths start with `prefix`.
    ///
    /// Returned paths are relative to this storage root, like every other [`Storage`] operation.
    fn list(&self, _prefix: &Path) -> ListObjectsStream {
        let err = anyhow::anyhow!(
            "listing objects is not supported for storage `{}`",
            self.uri(),
        );
        let storage_error = StorageErrorKind::Internal.with_error(err);
        stream::once(async move { Err(storage_error) }).boxed()
    }

    /// Returns whether a file exists or not.
    async fn exists(&self, path: &Path) -> StorageResult<bool> {
        match self.file_num_bytes(path).await {
            Ok(_) => Ok(true),
            Err(storage_err) if storage_err.kind() == StorageErrorKind::NotFound => Ok(false),
            Err(other_storage_err) => Err(other_storage_err),
        }
    }

    /// Returns a file size.
    async fn file_num_bytes(&self, path: &Path) -> StorageResult<u64>;

View on GitHub (pinned to a39730c5cd)