Calling `makemigrations` can call either `InteractiveMigrationQuestioner` or `NonInteractiveMigrationQuestioner`. When we send the flag `--no-input` to the `makemigrations` command it calls the non-interactive questioner. ``` if self.interactive: questioner = InteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run) else: questioner = NonInteractiveMigrationQuestioner(specified_apps=app_labels, dry_run=self.dry_run) ``` https://github.com/django/django/blob/290d8471bba35980f3e228f9c171afc40f2550fa/django/core/management/commands/makemigrations.py#L135-L138 `NonInteractiveMigrationQuestioner` itself will return `sys.exit(3)` in two methods: ``` class NonInteractiveMigrationQuestioner(MigrationQuestioner): def ask_not_null_addition(self, field_name, model_name): # We can't ask the user, so act like the user aborted. sys.exit(3) def ask_not_null_alteration(self, field_name, model_name): # We can't ask the user, so set as not provided. return NOT_PROVIDED def ask_auto_now_add_addition(self, field_name, model_name): # We can't ask the user, so act like the user aborted. sys.exit(3) ``` https://github.com/django/django/blob/e90af8bad44341cf8ebd469dac57b61a95667c1d/django/db/migrations/questioner.py#L227-L239