﻿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
36184	Migrating forward to a replaced migration fails	Jacob Walls	Jacob Walls	"You can migrate backward to a replaced migration since #24900, but apparently not forward. The fix looks to be trivial.

Failing test:
{{{#!diff
diff --git a/tests/migrations/test_commands.py b/tests/migrations/test_commands.py
index 5ff5cd4b26..39fdbf1278 100644
--- a/tests/migrations/test_commands.py
+++ b/tests/migrations/test_commands.py
@@ -1325,6 +1325,16 @@ class MigrateTests(MigrationTestBase):
                 # Unmigrate everything.
                 call_command(""migrate"", ""migrations"", ""zero"", verbosity=0)
 
+    @override_settings(
+        MIGRATION_MODULES={""migrations"": ""migrations.test_migrations_squashed""}
+    )
+    def test_migrate_forward_to_squashed_migration(self):
+        try:
+            call_command(""migrate"", ""migrations"", ""0001_initial"", verbosity=0)
+        finally:
+            # Unmigrate everything.
+            call_command(""migrate"", ""migrations"", ""zero"", verbosity=0)
+
     @override_settings(
}}}
----
{{{#!py
  File ""/Users/.../django/django/db/migrations/executor.py"", line 67, in migration_plan
    for migration in self.loader.graph.forwards_plan(target):
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/Users/.../django/django/db/migrations/graph.py"", line 207, in forwards_plan
    raise NodeNotFoundError(""Node %r not a valid node"" % (target,), target)
django.db.migrations.exceptions.NodeNotFoundError: Node ('migrations', '0001_initial') not a valid node
}}}

Rough patch -- this is just a copy/paste of a block above, so an intelligent refactor would be the only interesting part.
{{{#!py
diff --git a/django/db/migrations/executor.py b/django/db/migrations/executor.py
index 13afa5988f..f57bc2b090 100644
--- a/django/db/migrations/executor.py
+++ b/django/db/migrations/executor.py
@@ -64,6 +64,15 @@ class MigrationExecutor:
                             plan.append((self.loader.graph.nodes[migration], True))
                             applied.pop(migration)
             else:
+                # If the target is missing, it's likely a replaced migration.
+                # Reload the graph without replacements.
+                if (
+                    self.loader.replace_migrations
+                    and target not in self.loader.graph.node_map
+                ):
+                    self.loader.replace_migrations = False
+                    self.loader.build_graph()
+                    return self.migration_plan(targets, clean_start=clean_start)
                 for migration in self.loader.graph.forwards_plan(target):
                     if migration not in applied:
                         plan.append((self.loader.graph.nodes[migration], False))
}}}
"	Bug	closed	Migrations	dev	Normal	fixed	squashed, squash		Ready for checkin	1	0	0	0	0	0
