The AUTH_USER_MODEL setting was not correctly defined, causing Django’s authentication system to fail when trying to determine the primary key type for the user model.

Common Causes and Fixes

  1. AUTH_USER_MODEL Not Set in settings.py

    • Diagnosis: Inspect your settings.py file. If you have a custom user model, this setting must be present.
    • Fix: Add or ensure the following line is present in your settings.py, replacing 'yourapp.CustomUser' with your actual app and model name:
      AUTH_USER_MODEL = 'yourapp.CustomUser'
      
    • Why it works: This explicitly tells Django which model to use as the user model. Without it, Django defaults to the built-in auth.User, and if you’ve already created migrations or a custom user model, this mismatch causes the error.
  2. Typo in AUTH_USER_MODEL String

    • Diagnosis: Double-check the spelling of your app name and model name within the AUTH_USER_MODEL string in settings.py. Ensure there are no extra spaces or incorrect characters.
    • Fix: Correct any typos. For example, if your app is named accounts and your model UserProfile, it should be:
      AUTH_USER_MODEL = 'accounts.UserProfile'
      
    • Why it works: Django uses this string to dynamically import your user model. A typo means it can’t find the specified model, leading to the None primary key type error.
  3. Custom User Model Not Defined in its App’s models.py

    • Diagnosis: Navigate to the models.py file of the app specified in AUTH_USER_MODEL. Verify that a model class actually exists there, inheriting from AbstractBaseUser and PermissionsMixin (or models.Model if you’re extending the default user model).
    • Fix: Ensure your models.py contains a valid user model definition. Example:
      # yourapp/models.py
      from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
      from django.db import models
      
      class CustomUser(AbstractBaseUser, PermissionsMixin):
          email = models.EmailField(unique=True)
          first_name = models.CharField(max_length=30, blank=True)
          last_name = models.CharField(max_length=30, blank=True)
          is_active = models.BooleanField(default=True)
          is_staff = models.BooleanField(default=False)
          date_joined = models.DateTimeField(auto_now_add=True)
      
          USERNAME_FIELD = 'email'
          REQUIRED_FIELDS = []
      
          objects = models.Manager() # Default manager
      
          def __str__(self):
              return self.email
      
    • Why it works: Django needs a concrete model class to reference. If the model doesn’t exist in the specified file, it can’t be loaded, and its primary key type remains undefined.
  4. Circular Imports Between Apps

    • Diagnosis: Examine the models.py files of apps that might be referencing your custom user model (e.g., through ForeignKey fields). Look for situations where App A imports something from App B, and App B imports something from App A (or a longer chain).
    • Fix: Break the circular dependency. Often, this involves moving shared models to a common app, using string references for ForeignKey fields (e.g., 'yourapp.CustomUser' instead of importing the model directly), or restructuring your models.
      # In another app's models.py, referencing CustomUser
      from django.db import models
      
      class UserProfileInfo(models.Model):
          user = models.OneToOneField('yourapp.CustomUser', on_delete=models.CASCADE)
          bio = models.TextField()
          # ...
      
    • Why it works: Circular imports can prevent modules from loading correctly during Django’s startup or migration process. Using string references defers the import until it’s absolutely necessary, often sidestepping the issue.
  5. Migrations Not Applied or Incorrectly Created After Changing AUTH_USER_MODEL

    • Diagnosis: Run python manage.py showmigrations. Check if migrations related to your custom user model and any related models have been applied. If you changed AUTH_USER_MODEL after initial migrations, you might need to recreate them.
    • Fix:
      1. Remove existing migration files for your user app (e.g., yourapp/migrations/0001_initial.py, 0002_auto_....py). Be careful: this deletes historical migration data.
      2. If you have foreign keys pointing to the old default user model, you might need to temporarily revert AUTH_USER_MODEL to 'auth.User', run makemigrations, then switch back to your custom model and run makemigrations again.
      3. Run python manage.py makemigrations yourapp (replace yourapp with your app name).
      4. Run python manage.py migrate.
    • Why it works: Django’s database schema relies on migrations to define and update tables. If migrations are missing, outdated, or conflict with the AUTH_USER_MODEL setting, the database schema won’t match what Django expects, leading to errors like this. Recreating migrations ensures the schema accurately reflects the current user model definition.
  6. Using ContentType Cache Issues (Less Common)

    • Diagnosis: This is rare, but sometimes stale ContentType cache entries can cause problems, especially in complex setups or after significant refactoring.
    • Fix: Clear the contenttypes cache. You can do this by deleting the contenttypes.ContentType entries from your database manually or by running a script that flushes this specific table. A more forceful approach is to delete the contenttypes.pyc file if it exists in your project’s root or within the django library cache directory (though this is usually unnecessary). A simpler, albeit blunt, method is python manage.py flush followed by python manage.py migrate, but this resets all data.
    • Why it works: ContentType is used internally by Django for various features, including permissions and generic relations. If its cache is corrupted or out of sync with the actual models, it can lead to unexpected errors when Django tries to resolve model information.

The next error you’ll likely encounter is a RelatedObjectDoesNotExist if you try to access a related object that was implicitly expected to exist based on the old, broken user model configuration.

Want structured learning?

Take the full Django course →