sqlalchemy/alembic · error · ValueError
Cannot call run_async with a sync engine
Error message
Cannot call run_async with a sync engine
What it means
run_async bridges a synchronous migration into an async function by reusing the underlying async connection. If the configured engine is a plain sync engine (not an AsyncEngine/AsyncConnection), dialect.is_async is False and there is nothing to await; the guard rejects the call rather than silently deadlocking.
Source
Thrown at alembic/operations/base.py:579
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 as
part of the :meth:`.EnvironmentContext.run_migrations`
method called from an ``env.py`` script, a standaloneView on GitHub (pinned to 44fb345033)
Solutions
- Configure env.py with create_async_engine and run_migrations_async, then run_async becomes valid.
- If the migration must stay sync, replace op.run_async(body) with the synchronous equivalent of body.
- Ensure the dialect's is_async flag is True (asyncpg, aiosqlite, asyncmy, etc.).
Example fix
// before
# env.py (sync)
engine = sqlalchemy.create_engine(URL)
with engine.connect() as conn:
context.configure(connection=conn)
...
# migration: op.run_async(seed) # -> ValueError
// after
# env.py (async)
from sqlalchemy.ext.asyncio import create_async_engine
async def run_migrations_online():
engine = create_async_engine(URL)
async with engine.connect() as conn:
await conn.run_sync(do_migrations) Defensive patterns
Strategy: type-guard
Validate before calling
conn = op.get_bind()
if conn is None or not conn.dialect.is_async:
raise RuntimeError("op.run_async requires an async engine/connection") Type guard
def is_async_bind(conn) -> bool:
return conn is not None and bool(getattr(conn.dialect, "is_async", False)) Prevention
- Configure env.py with create_async_engine for projects that use run_async.
- Use run_migrations_async + conn.run_sync(do_migrations) in env.py.
- Keep a single async path for both app and migrations.
When it happens
Trigger: Calling op.run_async(fn) when env.py configured context.configure() against a sync sqlalchemy.create_engine() connection, instead of sqlalchemy.ext.asyncio.create_async_engine().
Common situations: A project that mostly uses sync SQLAlchemy but added an async helper into a migration; copy-pasting a run_async snippet from an async project into a sync env.py; running tests with a sync engine against migrations designed for async.
Related errors
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/b1f0a9e5fcdab077.json.
Report an issue: GitHub.