From 65c56ec428f9b0a9d7c820896e699d0dd42144ee Mon Sep 17 00:00:00 2001 From: Arpit Jain Date: Mon, 15 Jun 2026 19:29:02 +0900 Subject: [PATCH] Skip user-condition validation when the auth table is missing validate_user queries the user table, and the system check that runs it (flag_conditions_check) only catches ValidationError. On a fresh database the system checks run before the auth tables exist (for example during the first migrate), so the query raised OperationalError / ProgrammingError and that error propagated out of the check and aborted the migration. Catch those database errors in validate_user and skip validation in that case; the username is still validated normally once the tables exist. Fixes #96 Signed-off-by: Arpit Jain --- flags/conditions/validators.py | 8 ++++++++ flags/tests/test_conditions_validators.py | 16 ++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/flags/conditions/validators.py b/flags/conditions/validators.py index c85e14a..80d35d5 100644 --- a/flags/conditions/validators.py +++ b/flags/conditions/validators.py @@ -3,6 +3,7 @@ from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.core.validators import RegexValidator +from django.db import OperationalError, ProgrammingError from django.utils import dateparse from flags.utils import strtobool @@ -45,6 +46,13 @@ def validate_user(value): UserModel.objects.get(**{UserModel.USERNAME_FIELD: value}) except UserModel.DoesNotExist as err: raise ValidationError("Enter the username of a valid user.") from err + except (OperationalError, ProgrammingError): + # The user table may not exist yet, for example when the system checks + # run during a migration against a fresh database (before the auth + # tables are created). The username cannot be checked in that case, so + # skip validation rather than letting the database error abort the + # migration. + pass def validate_date(value): diff --git a/flags/tests/test_conditions_validators.py b/flags/tests/test_conditions_validators.py index ed9c782..d389bbc 100644 --- a/flags/tests/test_conditions_validators.py +++ b/flags/tests/test_conditions_validators.py @@ -1,5 +1,8 @@ +from unittest import mock + from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError +from django.db import OperationalError, ProgrammingError from django.test import TestCase, override_settings from flags.conditions.validators import ( @@ -82,6 +85,19 @@ def test_custom_user_invalid(self): with self.assertRaises(ValidationError): validate_user("nottestuser") + def test_user_table_missing_is_skipped(self): + # If the user table does not exist yet (for example when the system + # checks run during a migration against a fresh database), the lookup + # raises a database error. Validation should be skipped rather than + # letting that error abort the migration. See GH-96. + User = get_user_model() + for exc in (OperationalError, ProgrammingError): + with mock.patch.object( + User.objects, "get", side_effect=exc("relation does not exist") + ): + # Must not raise. + validate_user("testuser") + class ValidateDateTestCase(TestCase): def test_invalid_date_strings(self):