{"id":"c6e9e47ef4273c1d","repo":"sqlalchemy/alembic","slug":"no-such-constraint-s","errorCode":null,"errorMessage":"No such constraint: '%s'","messagePattern":"No such constraint: '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/operations/batch.py","lineNumber":697,"sourceCode":"            if const.name in self.col_named_constraints:\n                col, const = self.col_named_constraints.pop(const.name)\n\n                for col_const in list(self.columns[col.name].constraints):\n                    if col_const.name == const.name:\n                        self.columns[col.name].constraints.remove(col_const)\n            elif constraint_name_string(const.name):\n                const = self.named_constraints.pop(const.name)\n            elif const in self.unnamed_constraints:\n                self.unnamed_constraints.remove(const)\n\n        except KeyError:\n            if _is_type_bound(const):\n                # type-bound constraints are only included in the new\n                # table via their type object in any case, so ignore the\n                # drop_constraint() that comes here via the\n                # Operations.implementation_for(alter_column)\n                return\n            raise ValueError(\"No such constraint: '%s'\" % const.name)\n        else:\n            if isinstance(const, PrimaryKeyConstraint):\n                for col in const.columns:\n                    self.columns[col.name].primary_key = False\n\n    def create_index(self, idx: Index) -> None:\n        self.new_indexes[idx.name] = idx  # type: ignore[index]\n\n    def drop_index(self, idx: Index) -> None:\n        try:\n            del self.indexes[idx.name]  # type: ignore[arg-type]\n        except KeyError:\n            raise ValueError(\"No such index: '%s'\" % idx.name)\n\n    def rename_table(self, *arg, **kw):\n        raise NotImplementedError(\"TODO\")\n","sourceCodeStart":679,"sourceCodeEnd":714,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/operations/batch.py#L679-L714","documentation":"Raised by ApplyBatchImpl.drop_constraint() after a KeyError while looking up the constraint name. The name is not present in named_constraints, col_named_constraints or unnamed_constraints, and the constraint is not type-bound (type-bound drops are silently ignored). This means the constraint being dropped does not exist on the table that batch mode reflected or was copied from.","triggerScenarios":"Inside batch_alter_table, calling batch_op.drop_constraint('some_name') where 'some_name' is not a constraint on the target table; dropping a constraint that was already dropped in the same batch; dropping a constraint whose name was changed/never existed; case/quoting mismatch in the constraint name.","commonSituations":"Stale migration referencing a constraint that a later/earlier revision already removed; typo in constraint name; mismatch between the name in metadata and the name reflected from the DB (e.g. naming convention differences); running a migration against a DB that is ahead of or behind the expected state.","solutions":["Inspect the live table for actual constraint names (e.g. via reflection / PRAGMA foreign_key_list / information_schema) and correct the name in the migration.","Confirm the constraint has not already been dropped by a prior revision or earlier in the same batch.","Guard the drop with an existence check or use if_exists semantics where supported.","If the constraint is type-bound, drop it via alter_column on the column type rather than drop_constraint."],"exampleFix":"// before\nwith op.batch_alter_table('user') as batch_op:\n    batch_op.drop_constraint('fk_user_old')  # not present -> ValueError\n\n// after\n# verify against the reflected table first\nfrom sqlalchemy import inspect\nconstraints = [c['name'] for c in inspect(op.get_bind()).get_foreign_keys('user')]\nwith op.batch_alter_table('user') as batch_op:\n    if 'fk_user_old' in constraints:\n        batch_op.drop_constraint('fk_user_old')","handlingStrategy":"validation","validationCode":"from sqlalchemy import inspect\n\ndef constraint_exists(bind, table, name) -> bool:\n    fks = [c['name'] for c in inspect(bind).get_foreign_keys(table)]\n    uqs = [c['name'] for c in inspect(bind).get_unique_constraints(table)]\n    cks = [c['name'] for c in inspect(bind).get_check_constraints(table)]\n    return name in (set(fks) | set(uqs) | set(cks))","typeGuard":null,"tryCatchPattern":"try:\n    batch_op.drop_constraint(name)\nexcept ValueError as e:\n    if 'No such constraint' in str(e):\n        pass  # already absent, treat as success or log\n    else:\n        raise","preventionTips":["Reflect the table and check constraint names before dropping.","Make migrations idempotent by guarding drops with existence checks.","Watch for constraints already removed in prior revisions."],"tags":["alembic","batch-mode","constraints","migrations","data-integrity"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}