Opened 8 hours ago

Last modified 10 minutes ago

#36695 assigned Bug

Model field validator with a generic parameter causes infinite recursion when making migrations

Reported by: Michal Dabski Owned by: Augusto Pontes
Component: Migrations Version: 4.2
Severity: Normal Keywords:
Cc: Michal Dabski Triage Stage: Accepted
Has patch: no Needs documentation: yes
Needs tests: yes Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by Michal Dabski)

Minimal code to reproduce (in models.py) in Django==4.2.25

from django.utils.deconstruct import deconstructible
from django.db import models

@deconstructible
class SchemaValidator:
    def __init__(self, expected_type: type):
        pass

    def __call__(self, *args, **kwargs):
        pass

class TestModel(models.Model):
    config: dict[str, float] = models.JSONField(validators=[SchemaValidator(dict[str, float])])

This triggers an error when running makemigrations:

$ ./manage.py makemigrations
Migrations for 'audit_builder':
  meg_forms\audit_builder\migrations\0083_alter_testmodel_config.py
    - Alter field config on testmodel
Traceback (most recent call last):
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 214, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 214, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 214, in serialize
    item_string, item_imports = serializer_factory(item).serialize()
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  [Previous line repeated 996 more times]
  File "C:\Users\Michal\src\mat-cms\.venv\Lib\site-packages\django\db\migrations\serializer.py", line 389, in serializer_factory
    if isinstance(value, type_):
       ^^^^^^^^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded

Debugging locally shows that:

  • removing generic parameters from the dict type passed to SchemaValidator does not trigger the error
  • The loop happens in django.db.migrations.serializer.IterableSerializer.serialize, it keeps recursively invoking serializer_factory(item).serialize() with item='*dict[str, float]' (GenericAlias)
  • the same behaviour is with similar generic types - list[str]
  • without the migration being created/applied, validation works as expected

Change History (5)

comment:1 by Michal Dabski, 8 hours ago

Description: modified (diff)

comment:2 by Michal Dabski, 8 hours ago

Description: modified (diff)

comment:3 by Augusto Pontes, 80 minutes ago

Hi michael, i will try to reproduce it, and see if i can give to you a suggestion of how to solve it, i will test if this is still happening on newer versions, in this case i will use the 5.2

comment:4 by Augusto Pontes, 33 minutes ago

Needs documentation: set
Needs tests: set
Owner: set to Augusto Pontes
Patch needs improvement: set
Status: newassigned

comment:5 by Augusto Pontes, 10 minutes ago

Triage Stage: UnreviewedAccepted
Note: See TracTickets for help on using tickets.
Back to Top