﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
33583	sqlmigrate crashes on replaces to nonexistent migration.	Amin Shah Gilani	nobody	"Hello,

This is my first bug report here so please ask for any additional details you need. I would also appreciate a workaround. If it is obvious, it escapes me.

== Summary

When an app is renamed with its migrations including a `replaces` reference to the old app and migration name (such as by squashing migrations), the behavior between `migrate` and `sqlmigrate` becomes inconsistent. `migrate` happily applies all migrations, but `sqlmigrate` reports an error.

== Other information:

* This bug was first observed in v3.2, but my demo shows it also affects v4.0.3.
* This bug affects installations using the [https://github.com/python-social-auth/social-app-django social-app-django] package, which renamed its app multiple times,
* I have a demo available [https://github.com/amingilani/django-bug-PoC here].

== Steps to reproduce:

**Step 1:** Create a migration file, in an app and then rename the app and migration. This will result in a migration similar to this:


{{{#!python

# alpha/migrations/0001_initial.py
class Migration(migrations.Migration):

    replaces = [
        ('first', '0001_initial'),
    ]


}}}

**Step 2:** Ensure you have migrations in another app, with the first migration the second app referencing the old migration:

{{{#!python

class Migration(migrations.Migration):

    dependencies = [
        ('first', '0001_initial'),
    ]

}}}

**Step 3:** Note that `migrate` will happily apply all migrations:

  {{{#!shell
python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, alpha, auth, beta, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying alpha.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying beta.0001_initial... OK
  Applying beta.0002_auto_20220318_0245... OK
  Applying beta.0003_auto_20220318_0247... OK
  Applying sessions.0001_initial... OK
  }}}

**Step 4:** However, `sqlmigrate` will raise an error:

 {{{#!shell
python3 manage.py sqlmigrate beta 0003
Traceback (most recent call last):
  File ""/Users/amin/sandbox/mysite/manage.py"", line 22, in <module>
    main()
  File ""/Users/amin/sandbox/mysite/manage.py"", line 18, in main
    execute_from_command_line(sys.argv)
  File ""/usr/local/lib/python3.9/site-packages/django/core/management/__init__.py"", line 446, in execute_from_command_line
    utility.execute()
  File ""/usr/local/lib/python3.9/site-packages/django/core/management/__init__.py"", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File ""/usr/local/lib/python3.9/site-packages/django/core/management/base.py"", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File ""/usr/local/lib/python3.9/site-packages/django/core/management/commands/sqlmigrate.py"", line 38, in execute
    return super().execute(*args, **options)
  File ""/usr/local/lib/python3.9/site-packages/django/core/management/base.py"", line 460, in execute
    output = self.handle(*args, **options)
  File ""/usr/local/lib/python3.9/site-packages/django/core/management/commands/sqlmigrate.py"", line 46, in handle
    loader = MigrationLoader(connection, replace_migrations=False)
  File ""/usr/local/lib/python3.9/site-packages/django/db/migrations/loader.py"", line 58, in __init__
    self.build_graph()
  File ""/usr/local/lib/python3.9/site-packages/django/db/migrations/loader.py"", line 276, in build_graph
    self.graph.validate_consistency()
  File ""/usr/local/lib/python3.9/site-packages/django/db/migrations/graph.py"", line 198, in validate_consistency
    [n.raise_error() for n in self.node_map.values() if isinstance(n, DummyNode)]
  File ""/usr/local/lib/python3.9/site-packages/django/db/migrations/graph.py"", line 198, in <listcomp>
    [n.raise_error() for n in self.node_map.values() if isinstance(n, DummyNode)]
  File ""/usr/local/lib/python3.9/site-packages/django/db/migrations/graph.py"", line 60, in raise_error
    raise NodeNotFoundError(self.error_message, self.key, origin=self.origin)
django.db.migrations.exceptions.NodeNotFoundError: Migration beta.0001_initial dependencies reference nonexistent parent node ('first', '0001_initial')
 }}}


**Note:** I have a demo available to try [https://github.com/amingilani/django-bug-PoC here].


== Actual Behavior

`sqlmirate` raises an error but `migrate` processes the migrations without a problem

== Expected Behavior

Both commands would consistently either raise an error on these migrations, or run without raising an error"	Bug	closed	Migrations	3.2	Normal	invalid	sqlmigrate, migrate, squash	David Wobrock	Unreviewed	0	0	0	0	0	0
