{"id":"74c0ee52c283b491","repo":"sqlalchemy/alembic","slug":"revision-s-is-not-a-member-of-branch-s","errorCode":null,"errorMessage":"Revision %s is not a member of branch '%s'","messagePattern":"Revision (.+?) is not a member of branch '(.+?)'","errorType":"exception","errorClass":"ResolutionError","httpStatus":null,"severity":"error","filePath":"alembic/script/revision.py","lineNumber":659,"sourceCode":"                    resolved_id,\n                )\n            elif len(revs) > 1:\n                raise ResolutionError(\n                    \"Multiple revisions start \"\n                    \"with '%s': %s...\"\n                    % (resolved_id, \", \".join(\"'%s'\" % r for r in revs[0:3])),\n                    resolved_id,\n                )\n            else:\n                revision = self._revision_map[revs[0]]\n\n        if check_branch and revision is not None:\n            assert branch_rev is not None\n            assert resolved_id\n            if not self._shares_lineage(\n                revision.revision, branch_rev.revision\n            ):\n                raise ResolutionError(\n                    \"Revision %s is not a member of branch '%s'\"\n                    % (revision.revision, check_branch),\n                    resolved_id,\n                )\n        return revision\n\n    def _filter_into_branch_heads(\n        self, targets: Iterable[_RevisionOrBase | None]\n    ) -> set[_RevisionOrBase | None]:\n        targets = set(targets)\n\n        for rev in list(targets):\n            assert rev\n            if targets.intersection(\n                self._get_descendant_nodes([rev], include_dependencies=False)\n            ).difference([rev]):\n                targets.discard(rev)\n        return targets","sourceCodeStart":641,"sourceCodeEnd":677,"githubUrl":"https://github.com/sqlalchemy/alembic/blob/44fb3450330204b222ff05135e1fbbbdb28c44db/alembic/script/revision.py#L641-L677","documentation":"Raised by _revision_for_ident when a check_branch is supplied and the resolved revision does not share lineage with that branch (per _shares_lineage). In other words, 'label@revid' was given but revid is not on the branch named by label. It is a ResolutionError.","triggerScenarios":"Issuing 'branch_a@<revid>' where revid lives on a different branch; cross-branch references in downgrade/upgrade commands; mislabeling a migration with the wrong branch_labels.","commonSituations":"Migrations that were moved between branches during a rebase; copy-paste of a revision id from one branch into a command scoped to another.","solutions":["Drop the branch scope and reference the revision directly if you just want that revision.","Verify the revision is actually on the intended branch by checking its branch_labels and ancestors.","Re-apply the correct branch_labels in the migration file if it was mislabeled."],"exampleFix":"# before\nalembic downgrade featurex@deadbeef  # not a member of featurex\n# after\nalembic downgrade deadbeef           # absolute, no branch scope","handlingStrategy":"validation","validationCode":"rev = script.get_revision(rev_id)\nbranch_rev = script.get_revision('%s@head' % branch_label)\nif not script._revision_map._shares_lineage(rev, [branch_rev]):\n    raise ValueError('%s is not on branch %s' % (rev_id, branch_label))","typeGuard":null,"tryCatchPattern":"from alembic.script.revision import ResolutionError\ntry:\n    rev = script.get_revision('%s@%s' % (branch_label, rev_id))\nexcept ResolutionError as e:\n    # not a member of branch; drop the scope\n    rev = script.get_revision(rev_id)","preventionTips":["Only scope by branch when the revision is genuinely on that branch.","Prefer absolute revision ids over branch-scoped references.","Verify lineage before issuing branch-scoped commands."],"tags":["branch-label","lineage","revision-resolution","alembic"],"analyzedSha":"44fb3450330204b222ff05135e1fbbbdb28c44db","analyzedAt":"2026-08-04T19:57:10.248Z","schemaVersion":2}