{"id":"b1f0a9e5fcdab077","repo":"sqlalchemy/alembic","slug":"cannot-call-run-async-with-a-sync-engine","errorCode":null,"errorMessage":"Cannot call run_async with a sync engine","messagePattern":"Cannot call run_async with a sync engine","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/operations/base.py","lineNumber":579,"sourceCode":"        transaction as the connection running in the migration context.\n\n        Any additional arg or kw_arg passed to this function are passed\n        to the provided async function.\n\n        .. versionadded: 1.11\n\n        .. note::\n\n            This method can be called only when alembic is called using\n            an async dialect.\n        \"\"\"\n        if not sqla_compat.sqla_14_18:\n            raise NotImplementedError(\"SQLAlchemy 1.4.18+ required\")\n        sync_conn = self.get_bind()\n        if sync_conn is None:\n            raise NotImplementedError(\"Cannot call run_async in SQL mode\")\n        if not sync_conn.dialect.is_async:\n            raise ValueError(\"Cannot call run_async with a sync engine\")\n        from sqlalchemy.ext.asyncio import AsyncConnection\n        from sqlalchemy.util import await_only\n\n        async_conn = AsyncConnection._retrieve_proxy_for_target(sync_conn)\n        return await_only(async_function(async_conn, *args, **kw_args))\n\n\nclass Operations(AbstractOperations):\n    \"\"\"Define high level migration operations.\n\n    Each operation corresponds to some schema migration operation,\n    executed against a particular :class:`.MigrationContext`\n    which in turn represents connectivity to a database,\n    or a file output stream.\n\n    While :class:`.Operations` is normally configured as\n    part of the :meth:`.EnvironmentContext.run_migrations`\n    method called from an ``env.py`` script, a standalone","sourceCodeStart":561,"sourceCodeEnd":597,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/operations/base.py#L561-L597","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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.)."],"exampleFix":"// before\n# env.py (sync)\nengine = sqlalchemy.create_engine(URL)\nwith engine.connect() as conn:\n    context.configure(connection=conn)\n    ...\n# migration: op.run_async(seed)  # -> ValueError\n// after\n# env.py (async)\nfrom sqlalchemy.ext.asyncio import create_async_engine\nasync def run_migrations_online():\n    engine = create_async_engine(URL)\n    async with engine.connect() as conn:\n        await conn.run_sync(do_migrations)","handlingStrategy":"type-guard","validationCode":"conn = op.get_bind()\nif conn is None or not conn.dialect.is_async:\n    raise RuntimeError(\"op.run_async requires an async engine/connection\")","typeGuard":"def is_async_bind(conn) -> bool:\n    return conn is not None and bool(getattr(conn.dialect, \"is_async\", False))","tryCatchPattern":null,"preventionTips":["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."],"tags":["run-async","sync-engine","async"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}