Opened 94 minutes ago
Last modified 6 minutes ago
#36878 assigned Bug
Migration's ModelState has varying type for unique_together and index_together options causing autodetector crash
| Reported by: | Markus Holtermann | Owned by: | Markus Holtermann |
|---|---|---|---|
| Component: | Migrations | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Lily | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
When leveraging the MigrationAutodetector to get the changes between two project states, the following exception is raised (on 5.2, but the same applies to the current master at commit b1ffa9a9d78b0c2c5ad6ed5a1d84e380d5cfd010):
Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "src/manage.py", line 67, in <module> management.execute_from_command_line(sys.argv) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ File ".venv/lib/python3.13/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() ~~~~~~~~~~~~~~~^^ File ".venv/lib/python3.13/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ File ".venv/lib/python3.13/site-packages/django/core/management/base.py", line 420, in run_from_argv self.execute(*args, **cmd_options) ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.13/site-packages/django/core/management/base.py", line 464, in execute output = self.handle(*args, **options) File "src/core/management/commands/some_command.py", line 94, in handle self._get_migrations_and_operations(section) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ File "src/core/management/commands/some_command.py", line 238, in _get_migrations_and_operations new_migrations = autodetector.changes(self.graph, trim_to_apps={"affiliates"}) File ".venv/lib/python3.13/site-packages/django/db/migrations/autodetector.py", line 67, in changes changes = self._detect_changes(convert_apps, graph) File ".venv/lib/python3.13/site-packages/django/db/migrations/autodetector.py", line 213, in _detect_changes self.generate_removed_altered_unique_together() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^ File ".venv/lib/python3.13/site-packages/django/db/migrations/autodetector.py", line 1718, in generate_removed_altered_unique_together self._generate_removed_altered_foo_together(operations.AlterUniqueTogether) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.13/site-packages/django/db/migrations/autodetector.py", line 1699, in _generate_removed_altered_foo_together ) in self._get_altered_foo_together_operations(operation.option_name): ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^ File ".venv/lib/python3.13/site-packages/django/db/migrations/autodetector.py", line 1668, in _get_altered_foo_together_operations new_value = set(new_value) if new_value else set() ~~~^^^^^^^^^^^ TypeError: unhashable type: 'list'
Reason:
The migration ModelState tracks the changes for all options (order_with_respect_to, unique_together, indexes, ...) in its options attribute, which is a simple dict. For most keys inside the dict, the value is just a list of something. However, for unique_together and index_together, the value should be a set of tuples (see the ModelState.from_model() method).
Unfortunately, there are situations inside the ProjectState's mutation functions (e.g. rename_field()) where the data type for model_state.options["unique_together"] is changed to list[list[str]]:
for option in ("index_together", "unique_together"): if option in options: options[option] = [ [new_name if n == old_name else n for n in together] for together in options[option] ]
Change History (1)
comment:1 by , 6 minutes ago
| Triage Stage: | Unreviewed → Accepted |
|---|---|
| Type: | Uncategorized → Bug |