{"id":"b6dcfd3caf38154c","repo":"sqlalchemy/alembic","slug":"not-a-valid-downgrade-target-from-current-heads","errorCode":null,"errorMessage":"Not a valid downgrade target from current heads","messagePattern":"Not a valid downgrade target from current heads","errorType":"exception","errorClass":"RevisionError","httpStatus":null,"severity":"error","filePath":"alembic/script/revision.py","lineNumber":1380,"sourceCode":"            ancestors = {\n                rev.revision\n                for rev in self._get_ancestor_nodes(\n                    [self._resolve_branch(branch_label)],\n                    include_dependencies=False,\n                )\n            }\n            # Intersection gives the root revisions we are trying to\n            # rollback with the downgrade.\n            roots = [\n                is_revision(rev)\n                for rev in self.get_revisions(\n                    {rev.revision for rev in roots}.intersection(ancestors)\n                )\n            ]\n\n            # Ensure we didn't throw everything away when filtering branches.\n            if len(roots) == 0:\n                raise RevisionError(\n                    \"Not a valid downgrade target from current heads\"\n                )\n\n        heads = self.get_revisions(upper)\n\n        # Aim is to drop :branch_revision; to do so we also need to drop its\n        # descendents and anything dependent on it.\n        downgrade_revisions = set(\n            self._get_descendant_nodes(\n                roots,\n                include_dependencies=True,\n                omit_immediate_dependencies=False,\n            )\n        )\n        active_revisions = set(\n            self._get_ancestor_nodes(heads, include_dependencies=True)\n        )\n","sourceCodeStart":1362,"sourceCodeEnd":1398,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/script/revision.py#L1362-L1398","documentation":"Raised by _collect_downgrade_revisions when a branch-scoped downgrade leaves zero root revisions after filtering candidates by the branch's ancestors. Effectively, the requested downgrade target is not reachable / not valid from the current heads on that branch. It is a RevisionError.","triggerScenarios":"Issuing a branch-scoped downgrade (e.g., 'alembic downgrade mybranch@<revid>') where the target is not on the current head lineage of mybranch, so after filtering roots the candidate set is empty.","commonSituations":"Attempting to downgrade a branch whose head has already been merged into / superseded by another branch; branch_label mismatch; targeting a revision that is not an ancestor of any current head on that branch.","solutions":["Drop the branch scope and downgrade by absolute revision id.","Confirm the current heads and the target's lineage with 'alembic history' before downgrading.","Ensure the branch you name actually contains a current head or a reachable ancestor of one."],"exampleFix":"# before\nalembic downgrade mybranch@deadbeef   # not valid from current heads\n# after\nalembic downgrade deadbeef             # absolute, unscoped","handlingStrategy":"validation","validationCode":"heads = script.get_heads()\nbranch_rev = script.get_revision('%s@head' % branch_label)\nif not script._revision_map._shares_lineage(branch_rev, heads):\n    raise ValueError(\n        'branch %s has no current head to downgrade from' % branch_label\n    )","typeGuard":null,"tryCatchPattern":"from alembic.script.revision import RevisionError\ntry:\n    command.downgrade(cfg, '%s@%s' % (branch_label, target))\nexcept RevisionError as e:\n    if 'Not a valid downgrade target' in str(e):\n        command.downgrade(cfg, target)  # retry unscoped","preventionTips":["Verify the branch still has a current head before branch-scoped downgrades.","Prefer absolute, unscoped revision ids.","Inspect current heads and lineage before downgrading across branches."],"tags":["downgrade","branch-label","lineage","alembic"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}