You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The last_update_time provided in the session object '2025-07-01 18:59:42' is earlier than the update_time in the storage_session '2025-07-01 18:59:56'. Please check if it is a stale session #1733
{"error": "The last_update_time provided in the session object '2025-07-01 18:59:42' is earlier than the update_time in the storage_session '2025-07-01 18:59:56'. Please check if it is a stale session."}
I tried with the following simple example and I cannot reproduce the error, so I suspect the error you saw was caused by some race conditions, for example, your application might be processing multiple events for the same session concurrently, leading to a race condition where an older session object is used to update the state.
If it is not easy to share a minimal runnable example, could you please let me know how I might modify my following test code to reproduce the error?
import random
from google.adk import Agent
from google.adk.tools.tool_context import ToolContext
from google.genai import types
def roll_die(sides: int, tool_context: ToolContext) -> int:
"""Roll a die and return the rolled result.
Args:
sides: The integer number of sides the die has.
Returns:
An integer of the result of rolling the die.
"""
result = random.randint(1, sides)
if not 'rolls' in tool_context.state:
tool_context.state['rolls'] = []
tool_context.state['rolls'] = tool_context.state['rolls'] + [result]
return result
async def check_prime(nums: list[int]) -> str:
"""Check if a given list of numbers are prime.
Args:
nums: The list of numbers to check.
Returns:
A str indicating which number is prime.
"""
primes = set()
for number in nums:
number = int(number)
if number <= 1:
continue
is_prime = True
for i in range(2, int(number**0.5) + 1):
if number % i == 0:
is_prime = False
break
if is_prime:
primes.add(number)
return (
'No prime numbers found.'
if not primes
else f"{', '.join(str(num) for num in primes)} are prime numbers."
)
root_agent = Agent(
model='gemini-2.0-flash',
name='hello_world_agent',
description=(
'hello world agent that can roll a dice of 8 sides and check prime'
' numbers.'
),
instruction="""
You roll dice and answer questions about the outcome of the dice rolls.
You can roll dice of different sizes.
You can use multiple tools in parallel by calling functions in parallel(in one request and in one round).
It is ok to discuss previous dice roles, and comment on the dice rolls.
When you are asked to roll a die, you must call the roll_die tool with the number of sides. Be sure to pass in an integer. Do not pass in a string.
You should never roll a die on your own.
When checking prime numbers, call the check_prime tool with a list of integers. Be sure to pass in a list of integers. You should never pass in a string.
You should not check prime numbers before calling the tool.
When you are asked to roll a die and check prime numbers, you should always make the following two function calls:
1. You should first call the roll_die tool to get a roll. Wait for the function response before calling the check_prime tool.
2. After you get the function response from roll_die tool, you should call the check_prime tool with the roll_die result.
2.1 If user asks you to check primes based on previous rolls, make sure you include the previous rolls in the list.
3. When you respond, you must include the roll_die result from step 1.
You should always perform the previous 3 steps when asking for a roll and checking prime numbers.
You should not rely on the previous history on prime results.
""",
tools=[
roll_die,
check_prime,
],
generate_content_config=types.GenerateContentConfig(
safety_settings=[
types.SafetySetting( # avoid false alarm about rolling dice.
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold=types.HarmBlockThreshold.OFF,
),
]
),
)
I tried with the following simple example and I cannot reproduce the error, so I suspect the error you saw was caused by some race conditions, for example, your application might be processing multiple events for the same session concurrently, leading to a race condition where an older session object is used to update the state.
If it is not easy to share a minimal runnable example, could you please let me know how I might modify my following test code to reproduce the error?
import random
from google.adk import Agent
from google.adk.tools.tool_context import ToolContext
from google.genai import types
def roll_die(sides: int, tool_context: ToolContext) -> int:
"""Roll a die and return the rolled result.
Args:
sides: The integer number of sides the die has.
Returns:
An integer of the result of rolling the die.
"""
result = random.randint(1, sides)
if not 'rolls' in tool_context.state:
tool_context.state['rolls'] = []
tool_context.state['rolls'] = tool_context.state['rolls'] + [result]
return result
async def check_prime(nums: list[int]) -> str:
"""Check if a given list of numbers are prime.
Args:
nums: The list of numbers to check.
Returns:
A str indicating which number is prime.
"""
primes = set()
for number in nums:
number = int(number)
if number <= 1:
continue
is_prime = True
for i in range(2, int(number**0.5) + 1):
if number % i == 0:
is_prime = False
break
if is_prime:
primes.add(number)
return (
'No prime numbers found.'
if not primes
else f"{', '.join(str(num) for num in primes)} are prime numbers."
)
root_agent = Agent(
model='gemini-2.0-flash',
name='hello_world_agent',
description=(
'hello world agent that can roll a dice of 8 sides and check prime'
' numbers.'
),
instruction="""
You roll dice and answer questions about the outcome of the dice rolls.
You can roll dice of different sizes.
You can use multiple tools in parallel by calling functions in parallel(in one request and in one round).
It is ok to discuss previous dice roles, and comment on the dice rolls.
When you are asked to roll a die, you must call the roll_die tool with the number of sides. Be sure to pass in an integer. Do not pass in a string.
You should never roll a die on your own.
When checking prime numbers, call the check_prime tool with a list of integers. Be sure to pass in a list of integers. You should never pass in a string.
You should not check prime numbers before calling the tool.
When you are asked to roll a die and check prime numbers, you should always make the following two function calls:
1. You should first call the roll_die tool to get a roll. Wait for the function response before calling the check_prime tool.
2. After you get the function response from roll_die tool, you should call the check_prime tool with the roll_die result.
2.1 If user asks you to check primes based on previous rolls, make sure you include the previous rolls in the list.
3. When you respond, you must include the roll_die result from step 1.
You should always perform the previous 3 steps when asking for a roll and checking prime numbers.
You should not rely on the previous history on prime results.
""",
tools=[
roll_die,
check_prime,
],
generate_content_config=types.GenerateContentConfig(
safety_settings=[
types.SafetySetting( # avoid false alarm about rolling dice.
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold=types.HarmBlockThreshold.OFF,
),
]
),
)
@seanzhou1023 Thanks for looking into this issue! I just reproduced the error with my above code. Here are the steps:
Started the server by running uvicorn main:app --workers 4 --host 0.0.0.0
Call /run api twice at roughly the same time on the same session id
3. Saw the error `ValueError: The last_update_time provided in the session object '2025-07-08 16:55:47'` is earlier than the update_time in the storage_session '2025-07-08 16:57:11'. Please check if it is a stale session.`
Actually, even if we use --workers 1, this error can still happen, because the requests are handled asynchronously anyway, as lone as the first request is awaiting some IO, the server will work on the second request.
@code2tan Could you please check if you have similar simultaneous requests on the same session id when you interact with the server? Is it intentional?
@akshatshaw Thanks for letting us know you have the same problem! We were waiting for @code2tan to confirm the root cause. Could you please confirm if the issue is caused by calling the api multiple times on the session id simultaneously? If so, could you please help us understand the use case for this simultaneous calls on the same session id?
We also encountered this stale session issue when we try to mutate session state (which calls append_event) in the middle of /run_sse (ADK version 1.19).
We adopted @dennisgera 's solution and successfully mitigated the stale session issue 🎉 .
Maybe @dennisgera 's implementation should be built-in in ADK.
Activity
veevortexiq commentedon Jul 2, 2025
Same problem..Happens when I use MySQL DB for session service uri
xuanyang15 commentedon Jul 2, 2025
Thanks for reporting this bug! Could you please provide the following information? which should be helpful for me to understand the problem
CodyTonn commentedon Jul 3, 2025
I used Alibaba Cloud's RDS database service, which is based on MySQL.
xuanyang15 commentedon Jul 4, 2025
Thanks for the additional information! Is it possible for you to share a minimal runnable example to reproduce it?
xuanyang15 commentedon Jul 7, 2025
I tried with the following simple example and I cannot reproduce the error, so I suspect the error you saw was caused by some race conditions, for example, your application might be processing multiple events for the same session concurrently, leading to a race condition where an older session object is used to update the state.
If it is not easy to share a minimal runnable example, could you please let me know how I might modify my following test code to reproduce the error?
folder tree
main.py
test.py
agent.py
CodyTonn commentedon Jul 8, 2025
main.py
I used this shell script to start project
the workers param setting is 4, I guess cased by this
seanzhou1023 commentedon Jul 8, 2025
@code2tan please share the contents under
sql_agentfolder for us to reproduce and debug.xuanyang15 commentedon Jul 8, 2025
@seanzhou1023 Thanks for looking into this issue! I just reproduced the error with my above code. Here are the steps:
uvicorn main:app --workers 4 --host 0.0.0.0/runapi twice at roughly the same time on the same session idActually, even if we use
--workers 1, this error can still happen, because the requests are handled asynchronously anyway, as lone as the first request isawaiting some IO, the server will work on the second request.@code2tan Could you please check if you have similar simultaneous requests on the same session id when you interact with the server? Is it intentional?
akshatshaw commentedon Jul 28, 2025
@xuanyang15 any update the issue still exists for me, if i call simultaneous /un api
xuanyang15 commentedon Jul 28, 2025
@akshatshaw Thanks for letting us know you have the same problem! We were waiting for @code2tan to confirm the root cause. Could you please confirm if the issue is caused by calling the api multiple times on the session id simultaneously? If so, could you please help us understand the use case for this simultaneous calls on the same session id?
26 remaining items
johnson-liang-appier commentedon Feb 6, 2026
We also encountered this stale session issue when we try to mutate session state (which calls
append_event) in the middle of/run_sse(ADK version 1.19).We adopted @dennisgera 's solution and successfully mitigated the stale session issue 🎉 .
Maybe @dennisgera 's implementation should be built-in in ADK.
GWeale commentedon Feb 9, 2026
Hi, I am closing this issue now as I am not able to reproduce this on the current repo. Please reopen this issue if you notice this still
TomShlaim commentedon Feb 9, 2026
@GWeale Maybe I’m missing it, but did any of the PRs for this issue get merged?
I can tell it's still happening on 1.20
veevortexiq commentedon Feb 9, 2026
@GWeale
I'm using 1.18 - Same Issue is still happening - Using CloudSQL PostGres as session DB
xuanyang15 commentedon Feb 9, 2026
I think 1063fa5 was submitted as a fix for this issue. Could you please have a try with the latest version?
fix: Strip timezone for PostgreSQL timestamps in DatabaseSessionService
chanchalchitwan commentedon Feb 10, 2026
I am using 1.21.0 along with cloud sql DB. I am also getting this issue.
fix: Strip timezone for PostgreSQL timestamps in DatabaseSessionService
sasha-gitg commentedon Mar 2, 2026
Resolved by 1063fa5
fix: Reload the stale session in database_session_service when the up…
fix: Strip timezone for PostgreSQL timestamps in DatabaseSessionService