sqlalchemy/alembic · error · NotImplementedError
Cannot call run_async in SQL mode
Error message
Cannot call run_async in SQL mode
What it means
run_async needs a real async-capable connection to wrap; in offline (SQL) mode get_bind() returns None and there is no underlying DBAPI connection to proxy. The guard rejects the call before attempting to await on a non-existent connection.
Source
Thrown at alembic/operations/base.py:577
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,
or a file output stream.
While :class:`.Operations` is normally configured asView on GitHub (pinned to 44fb345033)
Solutions
- Run the migration online (remove --sql / set as_sql=False) so a real connection exists.
- For offline SQL output, replace the run_async block with a plain op.execute('...') string.
- Restructure env.py so run_async paths are skipped in offline mode.
Example fix
// before
# invoked as: alembic upgrade head --sql
op.run_async(prepare_async_data) # -> NotImplementedError
// after
# run online instead
with engine.connect() as conn:
context.configure(connection=conn)
... Defensive patterns
Strategy: validation
Validate before calling
if context.is_offline_mode() or op.get_bind() is None:
raise RuntimeError("op.run_async requires a live (online) connection") Type guard
def has_online_bind(op) -> bool:
return op.get_bind() is not None Prevention
- Branch on context.is_offline_mode() before calling run_async.
- Strip run_async blocks from offline SQL generation paths.
- Document which migrations require online execution.
When it happens
Trigger: Calling op.run_async(...) inside a migration context configured with as_sql=True (e.g. 'alembic upgrade head --sql'), or any context where MigrationContext.bind is None.
Common situations: Generating an offline SQL script for a migration that contains run_async; an env.py that conditionally goes offline but still runs the migration body.
Related errors
- can't return inspector as this AutogenContext has no databas
- SQL parameters not allowed with as_sql
- SQLAlchemy 1.4.18+ required
- Cannot call run_async with a sync engine
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/400c5fcc53198109.json.
Report an issue: GitHub.