Repository navigation
Open
Labels
Description
Expected Behavior
Feature retrieval should not depend on local code. This also causes issues deleting/updating the feature store via the CLI.
Current Behavior
If I register a feature service that uses an on_demand_feature_view and try to get historical features from it I get the following error:
Traceback (most recent call last):
File "/Users/user/Git/repo/test.py", line 14, in <module>
features = feature_store.get_historical_features(
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/feature_store.py", line 1171, in get_historical_features
) = utils._get_feature_views_to_use(self._registry, self.project, features)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/utils.py", line 1075, in _get_feature_views_to_use
fv = registry.get_any_feature_view(name, project, allow_cache)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/infra/registry/registry.py", line 641, in get_any_feature_view
return proto_registry_utils.get_any_feature_view(registry_proto, name, project)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/infra/registry/proto_registry_utils.py", line 92, in wrapper
value = func(registry_proto, name, project)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/infra/registry/proto_registry_utils.py", line 145, in get_any_feature_view
return OnDemandFeatureView.from_proto(on_demand_feature_view)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/on_demand_feature_view.py", line 393, in from_proto
transformation = PandasTransformation.from_proto(
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/feast/transformation/pandas_transformation.py", line 150, in from_proto
udf=dill.loads(user_defined_function_proto.body),
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/dill/_dill.py", line 311, in loads
return load(file, ignore, **kwds)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/dill/_dill.py", line 297, in load
return Unpickler(file, ignore=ignore, **kwds).load()
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/dill/_dill.py", line 452, in load
obj = StockUnpickler.load(self)
File "/Users/user/.pyenv/versions/repo/lib/python3.10/site-packages/dill/_dill.py", line 442, in find_class
return StockUnpickler.find_class(self, module, name)
ModuleNotFoundError: No module named 'feature_services'
I don't get this error if I'm running it from a location that it can find this module, but of course we want to deploy this feature service to the feature store and call it from elsewhere.
Steps to reproduce
I am using a Redshift Offline Source.
feature service code:
merchandisability_feature_store = FeatureService(
name="merchandisability",
features=[
artwork_inquiries_feature_view,
artwork_metadata_feature_view,
artist_metadata_feature_view,
partner_metadata_feature_view,
purchase_metadata_feature_view,
artwork_age, <-- on demand feature view
],
)and I try to get features like so:
df = pd.DataFrame.from_dict(
{"user_id": ["user1"], "event_timestamp": datetime.now()}
)
feature_service = feature_store.get_feature_service("merchandisability")
features = feature_store.get_historical_features(
features=feature_service,
entity_df=df,
)Specifications
- Version: 0.53.0
- Platform: MacOS 15.4.1
- Subsystem:
Possible Solution
🤷
Reacted by BigyaPradhan
Activity
BigyaPradhan commentedon Oct 2, 2025
This also stops
feast uifrom working.adarshsm commentedon Jul 30, 2026
Root cause: ODFV loading eagerly deserializes the UDF.
get_any_feature_view(sdk/python/feast/infra/registry/proto_registry_utils.py:151) callsOnDemandFeatureView.from_protowithoutskip_udf, which runs_parse_transformation_from_proto→Pandas/PythonTransformation.from_proto→dill.loads(body). So any registry read that resolves an ODFV —list,feast ui,get_historical_features— raisesModuleNotFoundErrorwhen a single ODFV's UDF imports a module that isn't present in the reading environment, even for operations that never execute the UDF.The
skip_udfpath already exists (_parse_transformation_from_protoreturnsNonewhen it's set, andlist_all_feature_viewsthreads it through — the write path uses it), butget_any_feature_viewand the default read paths don't pass it, so they still crash.A few directions, each a slightly different philosophy — wanted to check which you'd prefer before implementing:
body_text/udf_stringfor display) so one bad UDF doesn't break reads of everything else. Executing that specific ODFV still fails loudly.skip_udfto the read paths that never execute UDFs (feast ui,list,delete), consistent with the existing opt-in approach.dill.loadsuntil the UDF is actually invoked.(1) fixes the reported symptoms with the least surface area and no change to a working view's semantics; (2) stays closest to the current
skip_udfdesign; (3) is the most thorough but the largest change. Happy to implement whichever direction you'd prefer.