sqlalchemy/alembic · error · NotImplementedError
SQLAlchemy 1.4.18+ required
Error message
SQLAlchemy 1.4.18+ required
What it means
Operations.run_async raises NotImplementedError when SQLAlchemy is older than 1.4.18. run_async relies on AsyncConnection._retrieve_proxy_for_target and await_only, both introduced in SQLAlchemy 1.4.18, so earlier versions cannot support calling async functions from sync migration code.
Solutions
- Upgrade SQLAlchemy: pip install 'SQLAlchemy>=1.4.18' (preferably the latest 2.x).
- Pin SQLAlchemy>=1.4.18 in requirements.txt / pyproject.toml to prevent regressions.
- If upgrade is impossible, avoid run_async and perform the work with a synchronous connection instead.
Example fix
# before: pinned old SQLA # requirements.txt SQLAlchemy==1.3.24 # after SQLAlchemy>=1.4.18
Defensive patterns
Strategy: validation
Validate before calling
import sqlalchemy
from alembic.util import sqla_compat
def can_run_async() -> bool:
return bool(sqla_compat.sqla_14_18)
if not can_run_async():
raise RuntimeError(f'SQLAlchemy>=1.4.18 required, got {sqlalchemy.__version__}') Type guard
def sqlalchemy_supports_run_async() -> bool:
import sqlalchemy
return tuple(int(x) for x in sqlalchemy.__version__.split('.')[:3]) >= (1, 4, 18) Prevention
- Pin SQLAlchemy>=1.4.18 in your dependency manifest.
- Check sqlalchemy.__version__ at app startup when async migrations are used.
- Lock the environment with a reproducible requirements file.
When it happens
Trigger: Calling op.run_async(some_async_fn) in a migration while the installed SQLAlchemy is < 1.4.18 (sqla_compat.sqla_14_18 is False).
Common situations: Pinned older SQLAlchemy in a legacy project; virtualenv with a downgraded SQLAlchemy; fresh checkout in an environment with an old requirements lock.
Related errors
- Cannot call run_async in SQL mode
- Cannot call run_async with a sync engine
- String or text() construct expected
AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11).
Data as JSON: /api/errors/e0413b1231c6c902.
Report an issue: GitHub.
Appendix: source
Thrown at alembic/operations/base.py:574
This method allows calling async functions from within the
synchronous ``upgrade()`` or ``downgrade()`` alembic migration
method.
The async connection passed to the callable shares the same
transaction as the connection running in the migration context.
Any additional arg or kw_arg passed to this function are passed
to the provided async function.
.. versionadded: 1.11
.. note::
This method can be called only when alembic is called using
an async dialect.
"""
if not sqla_compat.sqla_14_18:
raise NotImplementedError("SQLAlchemy 1.4.18+ required")
sync_conn = self.get_bind()
if sync_conn is None:
raise NotImplementedError("Cannot call run_async in SQL mode")
if not sync_conn.dialect.is_async:
raise ValueError("Cannot call run_async with a sync engine")
from sqlalchemy.ext.asyncio import AsyncConnection
from sqlalchemy.util import await_only
async_conn = AsyncConnection._retrieve_proxy_for_target(sync_conn)
return await_only(async_function(async_conn, *args, **kw_args))
class Operations(AbstractOperations):
"""Define high level migration operations.
Each operation corresponds to some schema migration operation,
executed against a particular :class:`.MigrationContext`
which in turn represents connectivity to a database,View on GitHub (pinned to 5551b5d35f)