sqlalchemy/alembic · error · TypeError
SQL parameters not allowed with as_sql
Error message
SQL parameters not allowed with as_sql
What it means
When the migration context is in as_sql (offline) mode, the impl writes SQL text to a file/stream rather than executing against a database. Bind parameters cannot be rendered to a script because there is no DB to substitute them; only literal SQL (optionally with literal_binds) is emitted. Passing params/multiparams in this mode is therefore rejected.
Source
Thrown at alembic/ddl/impl.py:220
"""
@property
def bind(self) -> Connection | None:
return self.connection
def _exec(
self,
construct: Executable | str,
execution_options: Mapping[str, Any] | None = None,
multiparams: Sequence[Mapping[str, Any]] | None = None,
params: Mapping[str, Any] = util.immutabledict(),
) -> CursorResult | None:
if isinstance(construct, str):
construct = text(construct)
if self.as_sql:
if multiparams is not None or params:
raise TypeError("SQL parameters not allowed with as_sql")
compile_kw: dict[str, Any]
if self.literal_binds and not isinstance(
construct, schema.DDLElement
):
compile_kw = dict(compile_kwargs={"literal_binds": True})
else:
compile_kw = {}
if TYPE_CHECKING:
assert isinstance(construct, ClauseElement)
compiled = construct.compile(dialect=self.dialect, **compile_kw)
self.static_output(
str(compiled).replace("\t", " ").strip()
+ self.command_terminator
)
return None
else:View on GitHub (pinned to 44fb345033)
Solutions
- Run the migration online (remove --sql / as_sql) so bind parameters can be executed.
- For offline SQL, inline the values: op.execute("UPDATE t SET x = 1").
- Set literal_binds=True in the migration context if you need parameterized SQL rendered with literal values.
Example fix
// before
op.execute(sa.text('UPDATE users SET active = :v'), params={'v': True})
# run as: alembic upgrade head --sql -> TypeError
// after
op.execute('UPDATE users SET active = true') Defensive patterns
Strategy: validation
Validate before calling
if context.is_offline_mode():
assert not params and multiparams is None, "Bind params not allowed in as_sql mode; inline values instead." Try / catch
try:
op.execute(text('...'), params=p)
except TypeError as e:
if 'as_sql' in str(e):
op.execute(render_literal_sql(stmt, p))
else: raise Prevention
- Branch on context.is_offline_mode() before parameterized op.execute().
- Inline literal values when generating SQL scripts.
- Enable literal_binds so parameters render to literals in offline mode.
When it happens
Trigger: Calling op.execute(text('...'), params=...) or op.bulk_insert(...) inside an offline (as_sql=True) migration where the operation carries bind parameters; invoking 'alembic upgrade head --sql' over a migration that uses parameterized statements.
Common situations: A migration written for online use that calls op.execute(sa.text('UPDATE t SET x=:x'), params={'x': 1}); running it in offline SQL dump mode; using bulk_insert in SQL generation mode with non-literal values without literal_binds.
Related errors
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/0bc6e00142b7ba20.json.
Report an issue: GitHub.