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
- 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.
- Update or correct the database driver / SQLAlchemy version so VARCHAR columns return Python str.
- 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
- Ensure the alembic_version.version_num column is a String/VARCHAR type.
- Use a driver that returns str for character columns.
- Validate the current revision type before passing it into alembic APIs.
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
- Don't know how to comma-format %r
- String or text() construct expected
- Can't drop table in batch mode
- Constraint must have a name
- No such constraint: '%s'
AI-assisted analysis of sqlalchemy/alembic@44fb345033 (2026-08-04).
Data as JSON: /data/errors/d84af8c6229c0346.json.
Report an issue: GitHub.