Please read this first
- Have you read the docs? Yes
- Have you searched for related issues? Yes
Describe the bug
In AsyncSQLiteSession, calling close() concurrently or repeatedly causes an AttributeError: 'NoneType' object has no attribute 'close'.
This occurs because close() checks if self._connection is None: outside self._lock without re-verifying inside async with self._lock:. When two concurrent tasks invoke close(), both pass the initial None check; the first task acquires self._lock, closes self._connection, and sets it to None. When the second task subsequently acquires self._lock, it attempts await self._connection.close() on None.
In addition, AsyncSQLiteSession lacks a self._closed state flag (unlike SQLiteSession). Consequently, calling get_items(), add_items(), pop_item(), or clear_session() after close() re-initializes a new database connection instead of raising RuntimeError("AsyncSQLiteSession is closed").
Debug information
- Agents SDK version: main (0.19.0+)
- Python version: Python 3.13.5
- Operating System: macOS
Repro steps
import asyncio
from agents.extensions.memory import AsyncSQLiteSession
async def main():
session = AsyncSQLiteSession("test_close_race")
await session.add_items([{"role": "user", "content": "hi"}])
# Concurrent close calls raise AttributeError
await asyncio.gather(session.close(), session.close())
asyncio.run(main())
Expected behavior
AsyncSQLiteSession.close() should be thread-safe, task-safe, and idempotent (subsequent and concurrent calls to close() should be safe no-ops).
Operations invoked on a closed AsyncSQLiteSession should raise RuntimeError("AsyncSQLiteSession is closed"), matching SQLiteSession behavior.
I intend to submit a pull request fixing this issue.
Please read this first
Describe the bug
In
AsyncSQLiteSession, callingclose()concurrently or repeatedly causes anAttributeError: 'NoneType' object has no attribute 'close'.This occurs because
close()checksif self._connection is None:outsideself._lockwithout re-verifying insideasync with self._lock:. When two concurrent tasks invokeclose(), both pass the initialNonecheck; the first task acquiresself._lock, closesself._connection, and sets it toNone. When the second task subsequently acquiresself._lock, it attemptsawait self._connection.close()onNone.In addition,
AsyncSQLiteSessionlacks aself._closedstate flag (unlikeSQLiteSession). Consequently, callingget_items(),add_items(),pop_item(), orclear_session()afterclose()re-initializes a new database connection instead of raisingRuntimeError("AsyncSQLiteSession is closed").Debug information
Repro steps
Expected behavior
AsyncSQLiteSession.close()should be thread-safe, task-safe, and idempotent (subsequent and concurrent calls toclose()should be safe no-ops).Operations invoked on a closed
AsyncSQLiteSessionshould raiseRuntimeError("AsyncSQLiteSession is closed"), matchingSQLiteSessionbehavior.I intend to submit a pull request fixing this issue.