RemoteOnlineStore.online_write_batch labelled the timestamps it sent to
the feature server with the literals "event_timestamp" and "created".
The server rebuilds the frame and resolves those columns by the names the
feature view's batch source configures, so any feature view using a
different timestamp_field or created_timestamp_column failed server-side
with KeyError: 'Field "..." does not exist in schema'.
The timestamp values were never lost, only labelled with names the server
does not look up. Resolve both column names from the batch source, and
keep the previous literals as the fallback when a name is not configured.
Closes feast-dev#6595
Signed-off-by: arose26 <145766958+arose26@users.noreply.github.com>
What this fixes
Closes #6595.
RemoteOnlineStore.online_write_batch labelled the timestamps in its request body
with the literals "event_timestamp" and "created":
The feature server rebuilds that frame verbatim (pd.DataFrame(request.df) in
feature_server.py) and hands it to the standard conversion, which resolves the
timestamp columns by the names the feature view's batch source configures
(sdk/python/feast/utils.py, _convert_arrow_fv_to_proto):
So for any feature view whose source sets timestamp_field or
created_timestamp_column to something other than those two literals, the client
emits the column under one name and the server looks it up under another:
The timestamp value is never lost — it is on the wire, just labelled with a name the
server does not look up. Client and server simply disagree on the column names.
The change
Resolve both column names from the feature view's batch source, falling back to the
previous literals when a name is not configured. That keeps the payload byte-identical
for the default-named case (which is why the existing
test_unix_timestamp_value_serialized_as_int still passes unchanged) and makes the
custom-named case round-trip.
This is the only site with the hardcoding — _convert_arrow_odfv_to_proto synthesizes
its own timestamps and is unaffected, and no other caller builds this payload.
Tests
Two tests in TestRemoteOnlineStoreWriteBatch, both failing before the change:
timestamps with the configured names.
actually pins the contract: it takes the payload this client produced, rebuilds the
frame the way the server does, runs _convert_arrow_fv_to_proto on it, and asserts
both timestamps survive. Without the fix this test reproduces the reported
KeyError: 'Field "..." does not exist in schema' directly.
Wider check: every unit test file touching the remote / write_to_online_store /
_convert_arrow paths (22 files) gives 219 passed, 5 skipped both with and without this
change. The 11 collection errors in that set are pre-existing missing optional
dependencies in my environment (sqlite_vec, boto3, redis, …), identical on both
sides. ruff check, ruff format and mypy feast/infra/online_stores/remote.py are
clean.
🤖 Written with Claude Code (Claude Opus 5), reviewed by @arose26.