v4: Task schedule lost and / or "cannot commit transaction" error from SQLite
Author: JacobHayesCreated Mar 6, 2025Updated Dec 1, 2025
Labelsbug
Things to check first
I have checked that my issue does not already have a solution in the FAQ
I have searched the existing issues and didn't find my bug already reported there
I have checked that my bug is still present in the latest release
Version
v4 @ #1030 (master crashes with the KeyError fixed in #1030)
What happened?
Running the script below ends up with one of two things happening, either it:
- stops scheduling jobs after running for a bit (0-3 minutes?)
- you'll eventually notice no more
prints from the jobs arrive. - this is not related to
max_concurrent_jobs- there's only 1 job running at a time here
- you'll eventually notice no more
- crashes with
cannot commit transaction - SQL statements in progressfrom SQLite- some searching mentioned
That error can happen when the values returned by a RETURNING clause are not used, but I'm not sure if there are other triggers. - perhaps we return early or have some
awaits in the middle of iterating over a result set that give other tasks time to run queries and conflict
- some searching mentioned
I had a couple extra prints scattered throughout the code, so the exact line numbers here may be off by a few:
Scheduler crashed
+ Exception Group Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 859, in run_until_stopped
| async with create_task_group() as task_group:
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 1178, in _process_jobs
| await wakeup_event.wait()
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 1766, in wait
| await self._event.wait()
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/asyncio/locks.py", line 213, in wait
| await fut
| asyncio.exceptions.CancelledError: Cancelled by cancel scope 1072e6750
|
| During handling of the above exception, another exception occurred:
|
| Exception Group Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 1130, in _process_jobs
| async with AsyncExitStack() as exit_stack:
| ~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 768, in __aexit__
| raise exc
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 751, in __aexit__
| cb_suppress = await cb(*exc_details)
| ^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1142, in _commit_impl
| self.engine.dialect.do_commit(self.connection)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 703, in do_commit
| dbapi_connection.commit()
| ~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 296, in commit
| self._handle_exception(error)
| ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 323, in _handle_exception
| raise error
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 294, in commit
| self.await_(self._connection.commit())
| ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only
| return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
| ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn
| value = await result
| ^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 155, in commit
| await self._execute(self._conn.commit)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute
| return await future
| ^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run
| result = function()
| sqlite3.OperationalError: cannot commit transaction - SQL statements in progress
|
| The above exception was the direct cause of the following exception:
|
| Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 1126, in extend_job_leases
| await self.data_store.extend_acquired_job_leases(
| self.identity, job_ids, self.lease_duration
| )
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/datastores/sqlalchemy.py", line 1117, in extend_acquired_job_leases
| async for attempt in self._retry():
| ...<11 lines>...
| await self._execute(conn, update)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 166, in __anext__
| do = await self.iter(retry_state=self._retry_state)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 153, in iter
| result = await action(retry_state)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/_utils.py", line 99, in inner
| return call(*args, **kwargs)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/__init__.py", line 398, in <lambda>
| self._add_action_func(lambda rs: rs.outcome.result())
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/concurrent/futures/_base.py", line 449, in result
| return self.__get_result()
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/concurrent/futures/_base.py", line 401, in __get_result
| raise self._exception
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/datastores/sqlalchemy.py", line 1119, in extend_acquired_job_leases
| async with self._begin_transaction() as conn:
| ~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 221, in __aexit__
| await anext(self.gen)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/datastores/sqlalchemy.py", line 221, in _begin_transaction
| async with AsyncExitStack() as exit_stack:
| ~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 768, in __aexit__
| raise exc
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 751, in __aexit__
| cb_suppress = await cb(*exc_details)
| ^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 221, in __aexit__
| await anext(self.gen)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/engine.py", line 1065, in begin
| async with conn.begin():
| ~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/ext/asyncio/engine.py", line 1418, in __aexit__
| await greenlet_spawn(self._proxied.__exit__, type_, value, traceback)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 201, in greenlet_spawn
| result = context.throw(*sys.exc_info())
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/util.py", line 147, in __exit__
| with util.safe_reraise():
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
| raise exc_value.with_traceback(exc_tb)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/util.py", line 145, in __exit__
| self.commit()
| ~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2629, in commit
| self._do_commit()
| ~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2734, in _do_commit
| self._connection_commit_impl()
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2705, in _connection_commit_impl
| self.connection._commit_impl()
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1144, in _commit_impl
| self._handle_dbapi_exception(e, None, None, None, None)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 2352, in _handle_dbapi_exception
| raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/base.py", line 1142, in _commit_impl
| self.engine.dialect.do_commit(self.connection)
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/engine/default.py", line 703, in do_commit
| dbapi_connection.commit()
| ~~~~~~~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 296, in commit
| self._handle_exception(error)
| ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 323, in _handle_exception
| raise error
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/dialects/sqlite/aiosqlite.py", line 294, in commit
| self.await_(self._connection.commit())
| ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only
| return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
| ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn
| value = await result
| ^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 155, in commit
| await self._execute(self._conn.commit)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 122, in _execute
| return await future
| ^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/aiosqlite/core.py", line 105, in run
| result = function()
| sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) cannot commit transaction - SQL statements in progress
| (Background on this error at: https://sqlalche.me/e/20/e3q8)
+------------------------------------
+ Exception Group Traceback (most recent call last):
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 751, in __aexit__
| cb_suppress = await cb(*exc_details)
| ^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.scratch/repro_sqlalchemy_deleted_schedule.py", line 29, in main
| await scheduler.run_until_stopped()
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 859, in run_until_stopped
| async with create_task_group() as task_group:
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Exception Group Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 1130, in _process_jobs
| async with AsyncExitStack() as exit_stack:
| ~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 768, in __aexit__
| raise exc
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/contextlib.py", line 751, in __aexit__
| cb_suppress = await cb(*exc_details)
| ^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 767, in __aexit__
| raise BaseExceptionGroup(
| "unhandled errors in a TaskGroup", self._exceptions
| )
| ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
+-+---------------- 1 ----------------
| Traceback (most recent call last):
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/_schedulers/async_.py", line 1126, in extend_job_leases
| await self.data_store.extend_acquired_job_leases(
| self.identity, job_ids, self.lease_duration
| )
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/datastores/sqlalchemy.py", line 1117, in extend_acquired_job_leases
| async for attempt in self._retry():
| ...<11 lines>...
| await self._execute(conn, update)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 166, in __anext__
| do = await self.iter(retry_state=self._retry_state)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/asyncio/__init__.py", line 153, in iter
| result = await action(retry_state)
| ^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/_utils.py", line 99, in inner
| return call(*args, **kwargs)
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/.venv/lib/python3.13/site-packages/tenacity/__init__.py", line 398, in <lambda>
| self._add_action_func(lambda rs: rs.outcome.result())
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/concurrent/futures/_base.py", line 449, in result
| return self.__get_result()
| ~~~~~~~~~~~~~~~~~^^
| File "/Users/jacobhayes/.local/share/uv/python/cpython-3.13.1-macos-aarch64-none/lib/python3.13/concurrent/futures/_base.py", line 401, in __get_result
| raise self._exception
| File "/Users/jacobhayes/src/github.com/agronholm/apscheduler/src/apscheduler/datastores/sqlalchemy.py", line 1119, in extend_acquired_job_leases
| async with self._begin_transaction() as conn:Source: agronholm/apscheduler