{"id":"86830460d40dc14f","repo":"sqlalchemy/alembic","slug":"this-migrationscript-instance-has-a-multiple-entry-868304","errorCode":null,"errorMessage":"This MigrationScript instance has a multiple-entry list for DowngradeOps; please use the downgrade_ops_list attribute.","messagePattern":"This MigrationScript instance has a multiple-entry list for DowngradeOps; please use the downgrade_ops_list attribute\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"alembic/operations/ops.py","lineNumber":2856,"sourceCode":"        else:\n            return self._upgrade_ops[0]\n\n    @upgrade_ops.setter\n    def upgrade_ops(self, upgrade_ops: UpgradeOps | list[UpgradeOps]) -> None:\n        self._upgrade_ops = util.to_list(upgrade_ops)\n        for elem in self._upgrade_ops:\n            assert isinstance(elem, UpgradeOps)\n\n    @property\n    def downgrade_ops(self) -> DowngradeOps | None:\n        \"\"\"An instance of :class:`.DowngradeOps`.\n\n        .. seealso::\n\n            :attr:`.MigrationScript.downgrade_ops_list`\n        \"\"\"\n        if len(self._downgrade_ops) > 1:\n            raise ValueError(\n                \"This MigrationScript instance has a multiple-entry \"\n                \"list for DowngradeOps; please use the \"\n                \"downgrade_ops_list attribute.\"\n            )\n        elif not self._downgrade_ops:\n            return None\n        else:\n            return self._downgrade_ops[0]\n\n    @downgrade_ops.setter\n    def downgrade_ops(\n        self, downgrade_ops: DowngradeOps | list[DowngradeOps]\n    ) -> None:\n        self._downgrade_ops = util.to_list(downgrade_ops)\n        for elem in self._downgrade_ops:\n            assert isinstance(elem, DowngradeOps)\n\n    @property","sourceCodeStart":2838,"sourceCodeEnd":2874,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/operations/ops.py#L2838-L2874","documentation":"Raised by the MigrationScript.downgrade_ops property when more than one DowngradeOps entry exists in _downgrade_ops. Mirrors the upgrade case: once multiple downgrade streams exist, the scalar property is disabled and you must use downgrade_ops_list.","triggerScenarios":"Accessing script.downgrade_ops on a MigrationScript populated with a list of multiple DowngradeOps; custom process_revision_directives that produce several downgrade passes corresponding to multiple upgrade passes.","commonSituations":"Custom autogenerate hooks splitting downgrades into multiple DowngradeOps; template/render code reading the scalar property on a multi-pass script.","solutions":["Use script.downgrade_ops_list and iterate over all entries.","Ensure only one DowngradeOps is stored if the scalar accessor is required.","Branch rendering logic on len(downgrade_ops_list) > 1."],"exampleFix":"// before\nops = script.downgrade_ops  # raises ValueError when multiple\n\n// after\nfor ops in script.downgrade_ops_list:\n    ...","handlingStrategy":"type-guard","validationCode":"def get_downgrade_ops(script):\n    n = len(script.downgrade_ops_list)\n    if n > 1:\n        return script.downgrade_ops_list\n    return script.downgrade_ops_list[0] if n == 1 else None","typeGuard":"def has_multiple_downgrade_ops(script) -> bool:\n    return len(script.downgrade_ops_list) > 1","tryCatchPattern":"try:\n    ops = script.downgrade_ops\nexcept ValueError:\n    ops = script.downgrade_ops_list","preventionTips":["Prefer downgrade_ops_list in generic/render code.","Branch on len(downgrade_ops_list) in autogenerate hooks.","Keep scalar access to the single-entry case."],"tags":["alembic","autogenerate","migrations","internals"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}