sqlalchemy/alembic · error · NotImplementedError

SQLAlchemy 2.0 required

Error message

SQLAlchemy 2.0 required

What it means

Raised as NotImplementedError('SQLAlchemy 2.0 required') by the DropConstraintOp implementation (toimpl.py:226-233) when the operation's if_exists argument is set and the installed SQLAlchemy is older than 2.0. The `if_exists` kwarg for DROP CONSTRAINT relies on SQLAlchemy 2.0+ DDL features; sqla_2 (sqla_compat.py:69) gates it, so pre-2.0 installs cannot honour the flag.

Solutions

  1. Upgrade SQLAlchemy to >= 2.0 (pip install 'SQLAlchemy>=2.0').
  2. Remove the if_exists=True argument and handle existence yourself (e.g. query the catalog first), keeping SQLAlchemy 1.4.
  3. Pin Alembic to a version compatible with your SQLAlchemy 1.4 install if upgrading SQLAlchemy is not possible.

Example fix

// before (SQLAlchemy 1.4)
op.drop_constraint('ck_t', 't', type_='check', if_exists=True)  # raises
// after
op.drop_constraint('ck_t', 't', type_='check')  # SQLAlchemy 1.4 compatible
Defensive patterns

Strategy: validation

Validate before calling

# Check SQLAlchemy version before using if_exists on drop_constraint.
import sqlalchemy
from alembic.util.sqla_compat import sqla_2

def drop_constraint_maybe(name, table, type_, if_exists=False):
    if if_exists and not sqla_2:
        raise RuntimeError(
            f'drop_constraint(if_exists=True) needs SQLAlchemy>=2.0, got {sqlalchemy.__version__}'
        )
    op.drop_constraint(name, table, type_=type_, if_exists=if_exists if sqla_2 else None)

Type guard

from alembic.util.sqla_compat import sqla_2

def supports_drop_if_exists() -> bool:
    return sqla_2

Prevention

When it happens

Trigger: Calling op.drop_constraint('ck', 't', type_='check', if_exists=True) while running SQLAlchemy < 2.0 (e.g. 1.4.x). The implementation_for function checks `if operation.if_exists is not None and not sqla_2` and raises before touching the DB.

Common situations: Projects pinned to SQLAlchemy 1.4 (legacy apps) that pick up a newer Alembic migration using if_exists; CI with an older SQLAlchemy than local dev; dependency resolver installing an old SQLAlchemy.

Related errors


AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11). Data as JSON: /api/errors/b48faa1b6f493a97. Report an issue: GitHub.

Appendix: source

Thrown at alembic/operations/toimpl.py:233


@Operations.implementation_for(ops.AddConstraintOp)
def create_constraint(
    operations: "Operations", operation: "ops.AddConstraintOp"
) -> None:
    operations.impl.add_constraint(
        operation.to_constraint(operations.migration_context)
    )


@Operations.implementation_for(ops.DropConstraintOp)
def drop_constraint(
    operations: "Operations", operation: "ops.DropConstraintOp"
) -> None:
    kw = {}
    if operation.if_exists is not None:
        if not sqla_2:
            raise NotImplementedError("SQLAlchemy 2.0 required")
        kw["if_exists"] = operation.if_exists
    operations.impl.drop_constraint(
        operations.schema_obj.generic_constraint(
            operation.constraint_name,
            operation.table_name,
            operation.constraint_type,
            schema=operation.schema,
        ),
        **kw,
    )


@Operations.implementation_for(ops.BulkInsertOp)
def bulk_insert(
    operations: "Operations", operation: "ops.BulkInsertOp"
) -> None:
    operations.impl.bulk_insert(  # type: ignore[union-attr]
        operation.table, operation.rows, multiinsert=operation.multiinsert

View on GitHub (pinned to 5551b5d35f)