﻿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
24900	KeyError when trying to migrate backward to a replaced migration	Carl Meyer	Jacob Walls	"Django exhibits some internal confusion regarding whether replaced migrations exist or not. Consider this simple app with two migrations and squashed migration replacing both:

{{{
$ ls testproj/migrations/
0001_initial.py  0001_squashed_0002_thing_age.py  0002_thing_age.py  __init__.py
}}}

When it comes to disambiguating input, Django seems to believe that the replaced migrations still need to be considered:

{{{
$ ./manage.py migrate testproj 0001
CommandError: More than one migration matches '0001' in app 'testproj'. Please be more specific.
}}}

But if you actually try to disambiguate and specify one of the replaced migrations, Django no longer thinks it exists (and isn't very graceful about telling you so):

{{{
$ ./manage.py migrate testproj 0001_initial
Traceback (most recent call last):
  File ""./manage.py"", line 10, in <module>
    execute_from_command_line(sys.argv)
  File ""/home/carljm/projects/django/django/django/django/core/management/__init__.py"", line 330, in execute_from_command_line
    utility.execute()
  File ""/home/carljm/projects/django/django/django/django/core/management/__init__.py"", line 322, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File ""/home/carljm/projects/django/django/django/django/core/management/base.py"", line 347, in run_from_argv
    self.execute(*args, **cmd_options)
  File ""/home/carljm/projects/django/django/django/django/core/management/base.py"", line 398, in execute
    output = self.handle(*args, **options)
  File ""/home/carljm/projects/django/django/django/django/core/management/commands/migrate.py"", line 135, in handle
    plan = executor.migration_plan(targets)
  File ""/home/carljm/projects/django/django/django/django/db/migrations/executor.py"", line 50, in migration_plan
    self.loader.graph.node_map[target].children
KeyError: ('testproj', '0001_initial')
}}}

There could be several different approaches to fixing this, but my feeling is that Django shouldn't prevent you from migrating to a replaced migration. If a migration still exists on disk, even if it's been squashed and you've fully migrated the squashed set, you should be able to migrate back to a state within the squashed set. It seems like there might be production rollback cases where that could be important, and I don't see in principle why it shouldn't be possible.

If that turns out to be impractical, then I think Django oughtn't bother you about resolving ambiguities with migration names it won't let you migrate to anyway. And the ""nonexistent"" error for this case should be nicer than a raw `KeyError`. (In Django 1.7 the error was ""ValueError: Node ('testproj17', '0001_initial') not a valid node"", which is perhaps a bit better, but not much.)"	Bug	closed	Migrations	dev	Normal	fixed		Shai Berger	Ready for checkin	1	0	0	0	0	0
