fix: guard non-positive session limits and close() race in SQLite sessions#3413
Closed
rmotgi1227 wants to merge 1 commit into
Closed
fix: guard non-positive session limits and close() race in SQLite sessions#3413rmotgi1227 wants to merge 1 commit into
rmotgi1227 wants to merge 1 commit into
Conversation
…sions
AsyncSQLiteSession.get_items() and SQLAlchemySession.get_items() passed
the resolved session_limit directly to SQL LIMIT without checking whether
the value is non-positive. MongoDB and Redis already guard this:
if session_limit is not None and session_limit <= 0:
return []
Without the guard, SQLite treats LIMIT -1 as 'no limit' and returns all
rows, while MongoDB/Redis would return []. This inconsistency means the
same SessionSettings(limit=-1) produces different histories depending on
which backend is used.
Also fix a TOCTOU race in AsyncSQLiteSession.close(): the None check
happened outside the asyncio lock, so two concurrent close() calls could
both pass the guard and the second one would call .close() on a None
connection. Add a second check inside the lock (standard double-checked
pattern).
Changes:
- src/agents/extensions/memory/async_sqlite_session.py: add non-positive
limit guard in get_items(); add inside-lock None re-check in close()
- src/agents/extensions/memory/sqlalchemy_session.py: add non-positive
limit guard in get_items()
- tests: extend existing limit tests with limit=-1 assertions for both
AsyncSQLiteSession and SQLAlchemySession
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related correctness bugs in the SQLite-backed session implementations.
1. Non-positive
session_limitparity gap (AsyncSQLiteSession+SQLAlchemySession)MongoDBSession.get_itemsandRedisSession.get_itemsboth short-circuit withreturn []when the resolved limit is<= 0:AsyncSQLiteSessionandSQLAlchemySessionpass the limit directly to SQL without this guard. The consequence differs by sign:0LIMIT 0[]✓ (correct by accident)[]-1LIMIT -1[]SQLite interprets
LIMIT -1as "no limit" (SQLite docs), soget_items(limit=-1)returns the full history instead of an empty list. This is a silent behavioral difference between backends for the sameSessionSettings(limit=-1).Fix: add the same
<= 0guard before the SQL branch in bothAsyncSQLiteSession.get_itemsandSQLAlchemySession.get_items.2. TOCTOU race in
AsyncSQLiteSession.close()Two concurrent
await session.close()calls can both pass the outeris Nonecheck before either acquires the lock. The second call then invokes.close()onNone→AttributeError.Fix: add a second
if self._connection is None: returninside the lock (standard double-checked pattern).Test plan
test_async_sqlite_session_get_items_limitwithlimit=-1assertion (was already testinglimit=0)test_get_items_with_limitintest_sqlalchemy_session.pywithlimit=0andlimit=-1assertionsIssue number
No tracking issue — bugs discovered during code review.
Checks
make lintandmake format