Skip to content
Open
17 changes: 17 additions & 0 deletions src/google/adk/runners.py
Original file line number Diff line number Diff line change
Expand Up @@ -2333,13 +2333,30 @@ async def _setup_context_for_resumed_invocation(
ValueError: If the session has no events to resume; If no user message is
available for resuming the invocation; Or if the app is not resumable.
"""

if not session.events:
raise ValueError(f'Session {session.id} has no events to resume.')

# Step 1: Maybe retrieve a previous user message for the invocation.
user_message = new_message or self._find_user_message_for_invocation(
session.events, invocation_id
)

# === [START FIX] Fallback mechanism ===
if not user_message and session.events:
# If exact invocation match failed, try to find the latest user message
# This handles cases where invocation IDs might have drifted or for generic resume
for event in reversed(session.events):
if event.author == 'user' and event.content:
logger.warning(
'Could not find user message for invocation %s. Falling back to '
'the latest user message in the session.',
invocation_id,
)
user_message = event.content
break
# === [END FIX] ===

if not user_message:
raise ValueError(
f'No user message available for resuming invocation: {invocation_id}'
Expand Down
5 changes: 3 additions & 2 deletions tests/unittests/test_import_loading.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,16 @@
'typing_inspection',
'zstandard',
# google.genai.types annotates optional fields with aiohttp and Pillow
# types and imports whichever of the two the environment happens to have.
# No ADK module imports either one, so these are absent in some installs.
# types and probes for httpx2 compatibility. It imports whichever packages
# the environment happens to have, so these are absent in some installs.
'PIL',
'aiohappyeyeballs',
'aiohttp',
'aiosignal',
'attr',
'defusedxml',
'frozenlist',
'httpx2',
'multidict',
'propcache',
'yarl',
Expand Down