SQLAlchemy "Can't load plugin: sqlalchemy.dialects:postgres" in CI
SQLAlchemy 1.4+ removed the postgres dialect alias; only postgresql is valid. A DATABASE_URL starting postgres:// (common from hosted providers) now fails to load a dialect.
What this error means
Engine creation fails with "sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres" when the URL scheme is postgres://.
sqlalchemy.exc.NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgresCommon causes
The URL uses the removed postgres:// scheme
A provider-supplied DATABASE_URL begins postgres://, an alias SQLAlchemy dropped in 1.4. Only postgresql:// resolves now.
An old URL survived a SQLAlchemy upgrade
Code that ran on SQLAlchemy 1.3 worked with postgres://; after upgrading, the same URL no longer loads a dialect.
How to fix it
Normalize the scheme to postgresql
Rewrite the scheme before building the engine so a provider URL works unchanged.
url = os.environ["DATABASE_URL"]
if url.startswith("postgres://"):
url = url.replace("postgres://", "postgresql://", 1)
engine = create_engine(url)Pick an explicit driver
Use a full scheme that names the driver so the dialect is unambiguous.
# postgresql+psycopg2:// or postgresql+psycopg://
DATABASE_URL=postgresql+psycopg2://user:pass@127.0.0.1:5432/appHow to prevent it
- Always use postgresql:// (or postgresql+driver://) in SQLAlchemy URLs.
- Normalize provider URLs that ship the legacy postgres:// scheme.
- Re-check connection URLs after a SQLAlchemy major upgrade.