Skip to content

FirestoreSessionService.list_sessions(user_id="") returns every user's sessions #7662

Description

@AkshayShah03

🔴 Required Information

Describe the Bug:
FirestoreSessionService.list_sessions(app_name=..., user_id="") returns the sessions of every user of the app, not only the sessions of user "".

src/google/adk/integrations/firestore/firestore_session_service.py checks if user_id: (twice in list_sessions), so an empty string falls through to the collection_group query that user_id=None uses to list all users. The other session services (InMemory, Sqlite, Database, Redis, VertexAI) treat "" as a user id and return only that user's sessions. #7171 fixed the same check in SqliteSessionService.

This matters when the user id comes from a request or auth context that can be empty: the caller gets other users' sessions back.

Steps to Reproduce:

  1. pip install google-adk==2.11.0 google-cloud-firestore
  2. Run the snippet below. It uses a mocked Firestore client: collection_group holds two other users' sessions, and the per-user collection for "" is empty.

Expected Behavior:

[] collection_group used: False

Observed Behavior:

[('alice', 's-alice'), ('bob', 's-bob')] collection_group used: True

Environment Details:

  • ADK Library Version: 2.11.0 (also reproduced on main at d324744)
  • Desktop OS: macOS
  • Python Version: 3.12.13

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A

🟡 Optional Information

Minimal Reproduction Code:

import asyncio
from unittest import mock

from google.adk.integrations.firestore.firestore_session_service import FirestoreSessionService


def doc(data):
  snapshot = mock.MagicMock(exists=True)
  snapshot.to_dict.return_value = data
  return snapshot


async def main():
  client = mock.MagicMock()
  # Sessions of two other users, returned by the all-users collection_group query.
  client.collection_group.return_value.where.return_value.get = mock.AsyncMock(
      return_value=[
          doc({"id": "s-alice", "appName": "app", "userId": "alice", "state": {}}),
          doc({"id": "s-bob", "appName": "app", "userId": "bob", "state": {}}),
      ]
  )
  # Every per-user lookup (sessions of user "", app and user state) is empty.
  any_ref = client.collection.return_value.document.return_value
  any_ref.get = mock.AsyncMock(return_value=mock.MagicMock(exists=False))
  user_ref = any_ref.collection.return_value.document.return_value
  user_ref.get = mock.AsyncMock(return_value=mock.MagicMock(exists=False))
  user_ref.collection.return_value.where.return_value.get = mock.AsyncMock(
      return_value=[]
  )

  async def get_all(refs):
    for _ in refs:
      yield mock.MagicMock(exists=False)

  client.get_all = get_all

  service = FirestoreSessionService(client=client)
  response = await service.list_sessions(app_name="app", user_id="")
  print(
      [(s.user_id, s.id) for s in response.sessions],
      "collection_group used:",
      client.collection_group.called,
  )


asyncio.run(main())

How often has this issue occurred?:

  • Always (100%)

Proposed fix: Use if user_id is not None: in both places in list_sessions, as #7171 did for SqliteSessionService. I have a PR ready with a unit test.

Activity

  1. added
    services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc
    on Oct 22, 2026
  2. surajksharma07 commented on Oct 22, 2026

    @surajksharma07
    Collaborator

    Reproduced this on 2.12.0 too @AkshayShah03, list_sessions(user_id="") still falls through to the collection_group query.

    As a workaround until #7663 lands you could subclass FirestoreSessionService and return an empty ListSessionsResponse when user_id == "" before calling super().list_sessions(). The early return in af160d6 looks like the right approach.

    Could you give that a try in your setup and confirm it holds up for "", None and a normal user_id? Once you’ve verified it end to end please update the PR if anything changes so the reviewers can take it forward.

  3. AkshayShah03 commented on Oct 22, 2026

    @AkshayShah03
    ContributorAuthor

    Thanks @surajksharma07. Yes, I verified af160d6 end to end against the Firestore emulator (cloud-firestore-emulator v1.19.8) with sessions for two users:

    • user_id="" → [] (on main it returns both users' sessions)
    • user_id=None → all sessions for the app, unchanged
    • user_id="alice" → only alice's session, unchanged

    create_session(user_id="") is rejected by the backend (400 ... lacks a resource id), so no session can exist for "". The PR description has the details; nothing else needs to change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

services[Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions