alembic: `ValueError: Constraint must have a name` in alembic 1.10.0
Describe the bug
ValueError: Constraint must have a name in alembic 1.10.0.
Expected behavior
Migration succeeds.
To Reproduce Please try to provide a Minimal, Complete, and Verifiable example, with the migration script and/or the SQLAlchemy tables or models involved. See also Reporting Bugs on the website.
I’m trying to create a minimal reproducer now, but the migration script that caused the error looks like this:
"""Update run status constraint with killed
Revision ID: cfd24bdc0731
Revises: 89d4b8295536
Create Date: 2019-10-11 15:55:10.853449
"""
import alembic
from alembic import op
from packaging.version import Version
from sqlalchemy import CheckConstraint, Enum
from mlflow.entities import RunStatus, ViewType
from mlflow.entities.lifecycle_stage import LifecycleStage
from mlflow.store.tracking.dbmodels.models import SqlRun, SourceTypes
# revision identifiers, used by Alembic.
revision = "cfd24bdc0731"
down_revision = "2b4d017a5e9b"
branch_labels = None
depends_on = None
old_run_statuses = [
RunStatus.to_string(RunStatus.SCHEDULED),
RunStatus.to_string(RunStatus.FAILED),
RunStatus.to_string(RunStatus.FINISHED),
RunStatus.to_string(RunStatus.RUNNING),
]
new_run_statuses = [*old_run_statuses, RunStatus.to_string(RunStatus.KILLED)]
# Certain SQL backends (e.g., SQLite) do not preserve CHECK constraints during migrations.
# For these backends, CHECK constraints must be specified as table arguments. Here, we define
# the collection of CHECK constraints that should be preserved when performing the migration.
# The "status" constraint is excluded from this set because it is explicitly modified
# within the migration's `upgrade()` routine.
check_constraint_table_args = [
CheckConstraint(SqlRun.source_type.in_(SourceTypes), name="source_type"),
CheckConstraint(
SqlRun.lifecycle_stage.in_(LifecycleStage.view_type_to_stages(ViewType.ALL)),
name="runs_lifecycle_stage",
),
]
def upgrade():
# In alembic >= 1.7.0, `table_args` is unnecessary since CHECK constraints are preserved
# during migrations.
table_args = (
[] if Version(alembic.__version__) >= Version("1.7.0") else check_constraint_table_args
)
with op.batch_alter_table("runs", table_args=table_args) as batch_op:
# Transform the "status" column to an `Enum` and define a new check constraint. Specify
# `native_enum=False` to create a check constraint rather than a
# database-backend-dependent enum (see https://docs.sqlalchemy.org/en/13/core/
# type_basics.html#sqlalchemy.types.Enum.params.native_enum)
batch_op.alter_column(
"status",
type_=Enum(
*new_run_statuses,
create_constraint=True,
native_enum=False,
),
existing_type=Enum(
*old_run_statuses,
create_constraint=True,
native_enum=False,
name="status",
),
)
def downgrade():
# Omit downgrade logic for now - we don't currently provide users a command/API for
# reverting a database migration, instead recommending that they take a database backup
# before running the migration.
pass
Error
Traceback (most recent call last):
File "a.py", line 5, in <module>
with mlflow.start_run():
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/fluent.py", line 278, in start_run
client = MlflowClient()
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/client.py", line 69, in __init__
self._tracking_client = TrackingServiceClient(final_tracking_uri)
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/_tracking_service/client.py", line 51, in __init__
self.store
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/_tracking_service/client.py", line 55, in store
return utils._get_store(self.tracking_uri)
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/_tracking_service/utils.py", line 217, in _get_store
return _tracking_store_registry.get_store(store_uri, artifact_uri)
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/_tracking_service/registry.py", line 39, in get_store
return self._get_store_with_resolved_uri(resolved_store_uri, artifact_uri)
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/_tracking_service/registry.py", line 49, in _get_store_with_resolved_uri
return builder(store_uri=resolved_store_uri, artifact_uri=artifact_uri)
File "/home/haru/Desktop/repositories/mlflow/mlflow/tracking/_tracking_service/utils.py", line 150, in _get_sqlalchemy_store
return SqlAlchemyStore(store_uri, artifact_uri)
File "/home/haru/Desktop/repositories/mlflow/mlflow/store/tracking/sqlalchemy_store.py", line 134, in __init__
mlflow.store.db.utils._initialize_tables(self.engine)
File "/home/haru/Desktop/repositories/mlflow/mlflow/store/db/utils.py", line 82, in _initialize_tables
_upgrade_db(engine)
File "/home/haru/Desktop/repositories/mlflow/mlflow/store/db/utils.py", line 206, in _upgrade_db
command.upgrade(config, "heads")
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/command.py", line 378, in upgrade
script.run_env()
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/script/base.py", line 576, in run_env
util.load_python_file(self.dir, "env.py")
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/util/pyfiles.py", line 94, in load_python_file
module = load_module_py(module_id, path)
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/util/pyfiles.py", line 110, in load_module_py
spec.loader.exec_module(module) # type: ignore
File "<frozen importlib._bootstrap_external>", line 843, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File "/home/haru/Desktop/repositories/mlflow/mlflow/store/db_migrations/env.py", line 86, in <module>
run_migrations_online()
File "/home/haru/Desktop/repositories/mlflow/mlflow/store/db_migrations/env.py", line 80, in run_migrations_online
context.run_migrations()
File "<string>", line 8, in run_migrations
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/runtime/environment.py", line 867, in run_migrations
self.get_context().run_migrations(**kw)
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/runtime/migration.py", line 624, in run_migrations
step.migration_fn(**kw)
File "/home/haru/Desktop/repositories/mlflow/mlflow/store/db_migrations/versions/cfd24bdc0731_update_run_status_constraint_with_killed.py", line 57, in upgrade
batch_op.alter_column(
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/contextlib.py", line 120, in __exit__
next(self.gen)
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/operations/base.py", line 383, in batch_alter_table
impl.flush()
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/operations/batch.py", line 158, in flush
fn(*arg, **kw)
File "/home/haru/miniconda3/envs/mlflow-dev-env/lib/python3.8/site-packages/alembic/operations/batch.py", line 667, in add_constraint
raise ValueError("Constraint must have a name")
ValueError: Constraint must have a name
Versions.
- OS: Ubuntu 22.04
- Python: 3.8
- Alembic: 1.10.0
- SQLAlchemy: 2.0.0
- Database: SQLite
- DBAPI:
Additional context
The migration script works fine in alembic 1.9.4.
Have a nice day!
About this issue
- Original URL
- State: open
- Created a year ago
- Comments: 16 (8 by maintainers)
I’m not even creating a constraint and still running into this issue for
alembic==1.13.0yields
Can confirm for
alembic==1.13.1