neondatabase/neon · critical

not implemented

Error message

not implemented

What it means

LocalFileSystem, the local-directory backend of the remote_storage crate, does not implement versioned object listing. Its list_versions() body is the unimplemented!() macro, so calling it panics at runtime ('not implemented') instead of returning a DownloadError. Version-aware listing is only provided by object stores with real versioning semantics, e.g. the S3 backend.

Source

Thrown at libs/remote_storage/src/local_fs.rs:455

            cancel.cancelled().await;
            Err(DownloadError::Cancelled)
        };

        tokio::select! {
            res = op => res,
            res = timeout => res,
            res = cancelled => res,
        }
    }

    async fn list_versions(
        &self,
        _prefix: Option<&RemotePath>,
        _mode: ListingMode,
        _max_keys: Option<NonZeroU32>,
        _cancel: &CancellationToken,
    ) -> Result<crate::VersionListing, DownloadError> {
        unimplemented!()
    }

    async fn head_object(
        &self,
        key: &RemotePath,
        _cancel: &CancellationToken,
    ) -> Result<ListingObject, DownloadError> {
        let target_file_path = key.with_base(&self.storage_root);
        let metadata = file_metadata(&target_file_path).await?;
        Ok(ListingObject {
            key: key.clone(),
            last_modified: metadata.modified()?,
            size: metadata.len(),
        })
    }

    async fn upload(
        &self,

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Do not enable code paths that need versioned listing against a local backend; switch the storage configuration to an S3-compatible backend if version listing is required
  2. Return a proper DownloadError from LocalFileSystem::list_versions instead of unimplemented!() so callers can degrade gracefully
  3. If you own the feature, implement list_versions for LocalFileSystem (scan suffixed/versioned files) or gate the feature on backend capabilities

Example fix

// before (libs/remote_storage/src/local_fs.rs)
    async fn list_versions(...) -> Result<crate::VersionListing, DownloadError> {
        unimplemented!()
    }
// after
    async fn list_versions(...) -> Result<crate::VersionListing, DownloadError> {
        Err(DownloadError::BadInput(anyhow::anyhow!(
            "list_versions is not supported by the local filesystem backend",
        )))
    }
Defensive patterns

Strategy: validation

Validate before calling

// Before touching versioned listing, check backend capability
let supports_versions = !matches!(remote_storage_kind, RemoteStorageKind::LocalFs(_));
if !supports_versions {
    return Ok(Default::default()); // skip versioned GC / listing
}
let listing = storage.list_versions(prefix, mode, max_keys, cancel).await?;

Type guard

fn supports_list_versions(kind: &RemoteStorageKind) -> bool {
    !matches!(kind, RemoteStorageKind::LocalFs(_))
}

Try / catch

// It is a panic, not a Result: only catch_unwind can contain it if truly unavoidable
let res = std::panic::catch_unwind(AssertUnwindSafe(|| {
    storage.list_versions(prefix, mode, max_keys, cancel)
}));
if res.is_err() { /* fall back to unversioned listing */ }

Prevention

When it happens

Trigger: Calling list_versions() (directly or via GenericRemoteStorage) on a storage handle constructed for LocalFileSystem, e.g. a pageserver or compute configured with a local remote_storage backend when some code path requests ListingMode with versions. Any code that enumerates object versions (versioned GC, old-version cleanup) hits the panic immediately.

Common situations: Development or test environments that use local_fs remote storage while running a feature that was only exercised against S3 (works in staging with S3, panics locally); CI jobs that toggle the storage backend; deploying with a local prefix instead of an S3 bucket.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/9ea5241ce0d9fc74. Report an issue: GitHub.