sqlalchemy/alembic · error · NotImplementedError
Can't create table in batch mode
Error message
Can't create table in batch mode
What it means
BatchOperationsImpl.create_table raises NotImplementedError because creating an entirely new table is not meaningful inside a batch_alter_table block, which operates on an existing table by rebuilding it. The batch context only supports modifications to the target table, not creating additional tables.
Solutions
- Move op.create_table(...) outside the batch_alter_table block, calling it on the top-level Operations object.
- If the new table must be created alongside the batched alter, finish the batch block first, then create the table.
- Ensure code that conditionally creates tables does not run while a batch context is active.
Example fix
# before
with op.batch_alter_table('t') as batch_op:
batch_op.alter_column('c', type_=sa.Integer())
batch_op.create_table('other', ...) # error
# after
with op.batch_alter_table('t') as batch_op:
batch_op.alter_column('c', type_=sa.Integer())
op.create_table('other', ...) # outside batch Defensive patterns
Strategy: validation
Validate before calling
def safe_batch_block(op, table, batch_fn, *create_after):
with op.batch_alter_table(table) as batch_op:
batch_fn(batch_op)
for create in create_after:
op.create_table(create) # always outside batch Type guard
def is_outside_batch(op) -> bool:
# batch ops proxy is not the top-level Operations instance
return type(op).__name__ == 'Operations' Prevention
- Never call create_table inside a batch_alter_table block.
- Finish the batch context before creating additional tables.
- Use op (not batch_op) for any whole-table or whole-DB operation.
When it happens
Trigger: Calling batch_op.create_table(...) (or having Alembic route create_table through the batch impl) inside a with op.batch_alter_table(...) block.
Common situations: Calling the wrong op alias inside a batch block; a generic code path that dispatches create_table uniformly across batch and non-batch contexts.
Related errors
- The method does not apply to a batch table alter operation.
- No support for ALTER of constraints in SQLite dialect…
- recreate may be one of 'auto', 'always', or 'never'.
- TODO
- Can't drop table in batch mode
AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11).
Data as JSON: /api/errors/42a6b943b5b896a5.
Report an issue: GitHub.
Appendix: source
Thrown at alembic/operations/batch.py:198
self.batch.append(("drop_constraint", (const,), {}))
def rename_table(self, *arg, **kw):
self.batch.append(("rename_table", arg, kw))
def create_index(self, idx: Index, **kw: Any) -> None:
self.batch.append(("create_index", (idx,), kw))
def drop_index(self, idx: Index, **kw: Any) -> None:
self.batch.append(("drop_index", (idx,), kw))
def create_table_comment(self, table):
self.batch.append(("create_table_comment", (table,), {}))
def drop_table_comment(self, table):
self.batch.append(("drop_table_comment", (table,), {}))
def create_table(self, table):
raise NotImplementedError("Can't create table in batch mode")
def drop_table(self, table):
raise NotImplementedError("Can't drop table in batch mode")
def create_column_comment(self, column):
self.batch.append(("create_column_comment", (column,), {}))
class ApplyBatchImpl:
def __init__(
self,
impl: DefaultImpl,
table: Table,
table_args: tuple,
table_kwargs: dict[str, Any],
reflected: bool,
partial_reordering: tuple = (),
) -> None:View on GitHub (pinned to 5551b5d35f)