sqlalchemy/alembic · error · RevisionError

Ambiguous walk

Error message

Ambiguous walk

What it means

Raised by _walk when a relative walk (+n or -n steps) reaches a node with more than one next/previous revision, so the next step is ambiguous. Relative numeric offsets only work along an unambiguous single line; hitting a branch point or merge point makes the destination undefined. It is a RevisionError.

Source

Thrown at alembic/script/revision.py:1081

            else:
                # Walk down
                if initial == "base":
                    children = ()
                else:
                    children = self.get_revisions(
                        self.heads
                        if initial is None
                        else initial.down_revision
                    )
                    if not children:
                        children = ("base",)
            if not children:
                # This will return an invalid result if no_overwalk, otherwise
                # further steps will stay where we are.
                ret = None if no_overwalk else initial
                return ret
            elif len(children) > 1:
                raise RevisionError("Ambiguous walk")
            initial = children[0]

        return initial

    def _parse_downgrade_target(
        self,
        current_revisions: _RevisionIdentifierType,
        target: _RevisionIdentifierType,
        assert_relative_length: bool,
    ) -> tuple[str | None, _RevisionOrBase | None]:
        """
        Parse downgrade command syntax :target to retrieve the target revision
        and branch label (if any) given the :current_revisions stamp of the
        database.

        Returns a tuple (branch_label, target_revision) where branch_label
        is a string from the command specifying the branch to consider (or
        None if no branch given), and target_revision is a Revision object

View on GitHub (pinned to 44fb345033)

Solutions

  1. Use absolute revision ids or branch-scoped syntax (e.g., 'mybranch@-1') instead of bare relative offsets.
  2. Merge heads to restore a linear single line, then relative offsets become unambiguous.
  3. Specify the explicit target revision rather than a count.

Example fix

# before
alembic downgrade -1   # branch point -> Ambiguous walk
# after
alembic downgrade mybranch@-1   # or an explicit revision id
Defensive patterns

Strategy: validation

Validate before calling

heads = script.get_heads()
if len(heads) > 1:
    raise ValueError(
        'relative walk is ambiguous with heads: %s; scope a branch' % heads
    )

Try / catch

from alembic.script.revision import RevisionError
try:
    command.downgrade(cfg, '%s@-1' % branch)  # scoped, avoids ambiguity
except RevisionError as e:
    if 'Ambiguous walk' in str(e):
        # fall back to explicit revision id
        ...

Prevention

When it happens

Trigger: Issuing 'alembic upgrade +2' or 'downgrade -1' when the current position is a branch point with multiple children/parents; using relative offsets across a merge revision.

Common situations: Multi-head trees where '-1' from heads is ambiguous; relative downgrades after a merge; automation that assumes a linear history but the repo has branched.

Related errors


AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04). Data as JSON: /data/errors/722118700b260aa1.json. Report an issue: GitHub.