Skip to content

fix: use load_artifact instead of file_data in rewind artifact restoration#4979

Open
yuting0624 wants to merge 2 commits intogoogle:mainfrom
yuting0624:fix/4932-rewind-artifact-file-data
Open

fix: use load_artifact instead of file_data in rewind artifact restoration#4979
yuting0624 wants to merge 2 commits intogoogle:mainfrom
yuting0624:fix/4932-rewind-artifact-file-data

Conversation

@yuting0624
Copy link

Summary

Fixes #4932

Runner._compute_artifact_delta_for_rewind constructed a file_data reference to restore artifacts to their historical version during rewind. However:

  • GcsArtifactService raises NotImplementedError for file_data parts
  • FileArtifactService has no file_data handling path (falls through to validation error)

This caused rewind_async to crash for any application not using InMemoryArtifactService.

Fix

Use load_artifact(version=target_version) to read the historical version's actual bytes, then save_artifact with inline_data — which all artifact service implementations support.

This is consistent with how the "artifact did not exist at rewind point" case already works (lines 750–753 use inline_data).

Changes

  • src/google/adk/runners.py: Replace file_data reference construction with load_artifact + inline_data pattern (+18/-3 lines)

…ation (google#4932)

_compute_artifact_delta_for_rewind constructed a file_data reference
(types.Part(file_data=...)) to restore artifacts to their historical
version. However, GcsArtifactService raises NotImplementedError for
file_data parts, and FileArtifactService has no file_data handling
path, causing rewind_async to crash for all non-InMemory artifact
services.

Fix: use load_artifact to read the historical version's actual bytes,
then save_artifact with inline_data — which all artifact service
implementations support. This is consistent with how the 'artifact
did not exist at rewind point' case already works (lines 750-753).

Fixes google#4932
Comment on lines +768 to +773
artifact = types.Part(
inline_data=types.Blob(
mime_type=loaded.inline_data.mime_type,
data=loaded.inline_data.data,
)
)
Copy link

@lucasbarzotto-axonify lucasbarzotto-axonify Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(minor) load_artifact already returns a types.Part with inline_data populated, so the loaded part could be passed directly to save_artifact without re-wrapping into a new types.Part

Comment on lines +775 to +780
# Fallback: artifact couldn't be loaded, mark as empty.
artifact = types.Part(
inline_data=types.Blob(
mime_type='application/octet-stream', data=b''
)
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor suggestion: it might be worth logging a warning when the fallback is hit. A silent empty-blob replacement could be hard to debug if artifact storage is inconsistent

@rohityan rohityan self-assigned this Mar 24, 2026
@rohityan rohityan added request clarification [Status] The maintainer need clarification or more information from the author services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc labels Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

request clarification [Status] The maintainer need clarification or more information from the author services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runner._compute_artifact_delta_for_rewind saves artifacts with "file_data", which GcsArtifactService and FileArtifactService don't support

3 participants