◐ Shell
clean mode source ↗

fix: Auto-detect GCS/S3 registry store when registry is passed as string by jiwidi · Pull Request #6260 · feast-dev/feast

Problem

When passing registry="gs://bucket/feast/registry.pb" as a string to RepoConfig, Feast always creates a file-based RegistryConfig (hardcoded at repo_config.py line ~402). This ignores the URI scheme and causes FileRegistryStore to be used, which cannot handle gs:// paths — pathlib.Path("gs://...") is not treated as absolute, leading to IsADirectoryError at runtime.

The RegistryConfig docstring states:

If registry_type is 'file', then can be a local path, or remote object storage path, e.g. a GCS URI

But FileRegistryStore uses pathlib.Path which doesn't support GCS URIs.

Meanwhile, Registry.__init__ already has correct scheme-based auto-detection via get_registry_store_class_from_scheme() and REGISTRY_STORE_CLASS_FOR_SCHEME = {"gs": "GCSRegistryStore", ...} — it just never gets a chance because the RegistryConfig is pre-wrapped as "file" type.

Root Cause

In RepoConfig.registry property, the elif isinstance(self.registry_config, str) branch hardcodes:

self._registry = get_registry_config_from_type("file")(path=self.registry_config)

This wraps the path in a file-type config regardless of the URI scheme.

Reproduction

from feast.repo_config import RepoConfig

config = RepoConfig(
    project="test",
    provider="gcp",
    registry="gs://my-bucket/feast/registry.pb",
    online_store={"type": "redis", "connection_string": "localhost:6379"},
    entity_key_serialization_version=3,
)
# Before fix: config.registry.registry_store_type is implicitly "file"
#   -> FileRegistryStore -> Path("gs://...").is_absolute() == False
#   -> joins with repo_path -> IsADirectoryError
# After fix: config.registry.registry_store_type is None
#   -> Registry.__init__ auto-detects GCSRegistryStore from scheme

Fix

In RepoConfig.registry property, when registry is a string, create a plain RegistryConfig(path=...) instead of hardcoding get_registry_config_from_type("file"). This preserves registry_store_type=None, letting the existing auto-detection in Registry.__init__ select the correct store class based on the URI scheme.

Local file paths continue to work because registry_type defaults to "file" in RegistryConfig, and get_registry_store_class_from_scheme maps the file scheme (and schemeless paths) to FileRegistryStore.

Tests

Added test_registry_string_config.py with 11 tests covering:

  • GCS/S3/local string registry → correct RegistryConfig with registry_store_type=None
  • Dict registry (existing behavior preserved)
  • REGISTRY_STORE_CLASS_FOR_SCHEME maps gs→GCS, s3→S3, file→File
  • Unknown schemes raise
  • pathlib.Path cannot handle cloud URIs (documenting the underlying issue)

Open with Devin