sqlalchemy/alembic · error · ValueError
This MigrationScript instance has a multiple-entry list for…
Error message
This MigrationScript instance has a multiple-entry list for DowngradeOps; please use the downgrade_ops_list attribute.
What it means
Raised as ValueError by the MigrationScript.downgrade_ops getter (ops.py:2847-2859) when self._downgrade_ops has more than one entry. The exact mirror of the upgrade_ops (errorIndex 28) check: in multidb autogenerate, multiple DowngradeOps are stored and the singular accessor is intentionally disabled, pointing to downgrade_ops_list.
Solutions
- Use migration_script.downgrade_ops_list and iterate it.
- In custom hooks, write `for do in script.downgrade_ops_list: ...` instead of `script.downgrade_ops`.
- Confirm your env.py matches the single-DB pattern if you truly expect one DowngradeOps.
Example fix
// before
script = directives[0]
down = script.downgrade_ops # raises in multidb
// after
script = directives[0]
for down in script.downgrade_ops_list:
... # handle each DB's downgrade Defensive patterns
Strategy: validation
Validate before calling
# In process_revision_directives, always iterate the downgrade list.
def process_revision_directives(context, revision, directives):
script = directives[0]
for down_ops in script.downgrade_ops_list: # never script.downgrade_ops
... Type guard
from alembic.operations.ops import MigrationScript
def is_multidb(script: MigrationScript) -> bool:
return len(script._downgrade_ops) > 1 Try / catch
try:
down = script.downgrade_ops
except ValueError:
down = None
ops_list = script.downgrade_ops_list # always safe Prevention
- Use script.downgrade_ops_list in custom hooks; it works for single- and multi-DB.
- Check len(script._downgrade_ops) before the singular accessor.
- Treat any migration script as potentially multi-DB in generic tooling.
When it happens
Trigger: Accessing migration_script.downgrade_ops on a multi-database MigrationScript where >1 DowngradeOps were generated. Typically inside a process_revision_directives hook or custom renderer that assumes a single downgrade op.
Common situations: Multidb template migrations; refactoring a single-DB hook to run against a multi-DB project; assuming the script has one downgrade when env.py iterates engines.
Related errors
- This MigrationScript instance has a multiple-entry list for…
- constraint cannot be produced; original constraint is not…
- no dispatch function for object
- operation is not reversible; original column is not present
- A plugin named is already registered
AI-assisted analysis of sqlalchemy/alembic@5551b5d35f (2026-08-11).
Data as JSON: /api/errors/86830460d40dc14f.
Report an issue: GitHub.
Appendix: source
Thrown at alembic/operations/ops.py:2856
else:
return self._upgrade_ops[0]
@upgrade_ops.setter
def upgrade_ops(self, upgrade_ops: UpgradeOps | list[UpgradeOps]) -> None:
self._upgrade_ops = util.to_list(upgrade_ops)
for elem in self._upgrade_ops:
assert isinstance(elem, UpgradeOps)
@property
def downgrade_ops(self) -> DowngradeOps | None:
"""An instance of :class:`.DowngradeOps`.
.. seealso::
:attr:`.MigrationScript.downgrade_ops_list`
"""
if len(self._downgrade_ops) > 1:
raise ValueError(
"This MigrationScript instance has a multiple-entry "
"list for DowngradeOps; please use the "
"downgrade_ops_list attribute."
)
elif not self._downgrade_ops:
return None
else:
return self._downgrade_ops[0]
@downgrade_ops.setter
def downgrade_ops(
self, downgrade_ops: DowngradeOps | list[DowngradeOps]
) -> None:
self._downgrade_ops = util.to_list(downgrade_ops)
for elem in self._downgrade_ops:
assert isinstance(elem, DowngradeOps)
@propertyView on GitHub (pinned to 5551b5d35f)