sqlalchemy/alembic · error · RevisionError

revision identifier %r is not a string; ensure database driv

Error message

revision identifier %r is not a string; ensure database driver settings are correct

What it means

Raised by _resolve_revision_number when the supplied identifier is not a string (and not a tuple of strings). The message's 'database driver settings' hint reflects the classic cause: the value read from the database's version table came back as a non-string (e.g., bytes, int, or a custom type) because the version column type / driver doesn't return str. It is a RevisionError.

Source

Thrown at alembic/script/revision.py:752

                    [resolved_target],
                    include_dependencies=include_dependencies,
                )
            )
            .intersection(resolved_test_against_revs)
        )

    def _resolve_revision_number(
        self, id_: _GetRevArg | None
    ) -> tuple[tuple[str, ...], str | None]:
        branch_label: str | None
        if isinstance(id_, str) and "@" in id_:
            branch_label, id_ = id_.split("@", 1)

        elif id_ is not None and (
            (isinstance(id_, tuple) and id_ and not isinstance(id_[0], str))
            or not isinstance(id_, (str, tuple))
        ):
            raise RevisionError(
                "revision identifier %r is not a string; ensure database "
                "driver settings are correct" % (id_,)
            )

        else:
            branch_label = None

        # ensure map is loaded
        self._revision_map
        if id_ == "heads":
            if branch_label:
                return (
                    self.filter_for_lineage(self.heads, branch_label),
                    branch_label,
                )
            else:
                return self._real_heads, branch_label
        elif id_ == "head":

View on GitHub (pinned to 44fb345033)

Solutions

  1. Check the alembic_version table column type and ensure version_num is a String/VARCHAR; alter the column if the driver coerces it to bytes or int.
  2. Update or correct the database driver / SQLAlchemy version so VARCHAR columns return Python str.
  3. If you pass ids programmatically, coerce to str before calling the API.

Example fix

# before (version_num column returns bytes)
# ALTER TABLE alembic_version ALTER COLUMN version_num TYPE varchar
# after
# ensure driver returns str; e.g. use psycopg2 (not a bytes-returning driver)
Defensive patterns

Strategy: validation

Validate before calling

from alembic.runtime.migration import MigrationContext
with engine.begin() as conn:
    ctx = MigrationContext.configure(conn)
    current = ctx.get_current_revision()
if not isinstance(current, str):
    raise RuntimeError(
        'version column returned %r, not str; check driver/column type'
        % type(current)
    )

Type guard

def is_str_revision(value) -> bool:
    return value is None or isinstance(value, str)

Try / catch

from alembic.script.revision import RevisionError
try:
    script.get_revision(current)
except RevisionError as e:
    if 'not a string' in str(e):
        # fix the version table column type / driver, then retry
        ...

Prevention

When it happens

Trigger: The version_num column in alembic_version returning bytes (e.g., some MySQL/psycopg2 configs), an integer, or None-wrapped objects; passing a non-string programmatically into upgrade/downgrade; SQLAlchemy column type mismatch on the version table.

Common situations: Switching database drivers (e.g., to a driver that returns bytes for VARCHAR); custom version_table schema where the column type isn't String; older alembic_version tables migrated to a new DB engine with different type coercion.

Related errors


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