Skip to content

DatabaseSessionService returns storage_events without ordering, causing out-of-sequence messages : 400 INVALID_ARGUMENT #453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
JoaoCampista opened this issue Apr 29, 2025 · 1 comment
Assignees
Labels
services Runtime services

Comments

@JoaoCampista
Copy link
Contributor

Describe the bug
The DatabaseSessionService class (in adk/sessions/database_session_service.py) fetches StorageEvent records without any ORDER BY clause. As a result, events are returned in a non-deterministic order determined by the database’s query planner. When building the context for inference via the Gemini API, messages end up shuffled, leading to hallucinations because the model receives them out of their original sequence.

To Reproduce

On src\google\adk\sessions\database_session_service.py:
Line 329:

`
def get_session(
self,
*,
app_name: str,
user_id: str,
session_id: str,
config: Optional[GetSessionConfig] = None,
) -> Optional[Session]:
# 1. Get the storage session entry from session table
# 2. Get all the events based on session id and filtering config
# 3. Convert and return the session
with self.DatabaseSessionFactory() as sessionFactory:
storage_session = sessionFactory.get(
StorageSession, (app_name, user_id, session_id)
)
if storage_session is None:
return None

  storage_events = (
      sessionFactory.query(StorageEvent)
      .filter(StorageEvent.session_id == storage_session.id)
      .filter(
          StorageEvent.timestamp < config.after_timestamp
          if config
          else True
      )
      .limit(config.num_recent_events if config else None)
      .all()
  )

`
on storage_events, is missing .sort:

Fixed:

`
def get_session(
self,
*,
app_name: str,
user_id: str,
session_id: str,
config: Optional[GetSessionConfig] = None,
) -> Optional[Session]:
# 1. Get the storage session entry from session table
# 2. Get all the events based on session id and filtering config
# 3. Convert and return the session
with self.DatabaseSessionFactory() as sessionFactory:
storage_session = sessionFactory.get(
StorageSession, (app_name, user_id, session_id)
)
if storage_session is None:
return None

  storage_events = (
      sessionFactory.query(StorageEvent)
      .filter(StorageEvent.session_id == storage_session.id)
      .filter(
          StorageEvent.timestamp < config.after_timestamp
          if config
          else True
      )
      .limit(config.num_recent_events if config else None)
      .order_by(StorageEvent.timestamp.asc())
      .all()
  )

`

Expected behavior
Events should always be returned in ascending order of their timestamp field, preserving the chronological sequence of messages.

Actual Behavior
The StorageEvent list is returned without ordering, resulting in a non-deterministic sequence.

Desktop (please complete the following information):

  • OS: Windows
  • Python 3.12.8
  • ADK version 0.3.0
@JoaoCampista JoaoCampista changed the title DatabaseSessionService returns storage_events without ordering, causing out-of-sequence messages DatabaseSessionService returns storage_events without ordering, causing out-of-sequence messages : 400 INVALID_ARGUMENT Apr 29, 2025
@JoaoCampista
Copy link
Contributor Author

This fix on #454 resolve the google.genai.errors.ClientError: 400 INVALID_ARGUMENT. {'error': {'code': 400, 'message': 'Please ensure that function call turn comes immediately after a user turn or after a function response turn.', 'status': 'INVALID_ARGUMENT'}}

Its because the order of messages after get_session on database its not chonological.

@hangfei hangfei added the services Runtime services label May 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
services Runtime services
Projects
None yet
3 participants