Не превышайте 32 символа в идентификаторах ревизий Alembic

Симптом

Команда alembic upgrade head завершается ошибкой при сохранении новой ревизии:

sqlalchemy.exc.DataError: (psycopg2.errors.StringDataRightTruncation)
value too long for type character varying(32)

DDL самой миграции выполняется успешно. Ошибка возникает, когда Alembic записывает идентификатор ревизии в свою служебную таблицу.

Контекст

Alembic хранит текущую версию схемы в единственной колонке version_num таблицы alembic_version. По умолчанию тип этой колонки - VARCHAR(32). Обычно Alembic генерирует случайные 12-символьные идентификаторы, поэтому ограничение незаметно. Оно проявляется, когда идентификаторы делают описательными вручную: например, передают --rev-id или переименовывают файлы в понятные слаги.

Корневая причина

Идентификатор длиннее 32 символов не помещается в alembic_version.version_num. Postgres не обрезает значение молча, а отклоняет INSERT или UPDATE с ошибкой StringDataRightTruncation, поэтому вся транзакция обновления откатывается.

Ошибочное предположение

Мы считали идентификатор ревизии обычной подписью, которую можно сделать сколь угодно подробной. На деле это значение, подобное первичному ключу: оно хранится в колонке фиксированной ширины, поэтому длина является жёстким ограничением схемы, а не косметическим свойством.

Исправление

Исправление сводилось к двум вариантам. Идентификаторы ревизий ограничивали 32 символами, а описание помещали в сообщение или имя файла. Если длинные идентификаторы действительно требовались, колонку расширяли отдельной миграцией:

op.alter_column(
    "alembic_version",
    "version_num",
    type_=sa.String(length=64),
)

Расширение даёт больше свободы ценой переносимости. Значение по умолчанию в 32 символа позволяет служебной таблице одинаково работать со всеми поддерживаемыми Alembic СУБД.

Общий вывод

Длина любого идентификатора, записываемого в колонку фиксированной ширины, ограничена этой колонкой, каким бы «свободным» он ни казался в исходном коде. Если инструмент сохраняет ваши подписи, считайте допустимую длину частью его контракта и проверяйте схему хранения до выбора формата имён.