zylon-ai/private-gpt · error · ValueError

Cannot resolve SQLAlchemy engine for migration store '{store

Error message

Cannot resolve SQLAlchemy engine for migration store '{store}'

What it means

When building the SQLAlchemy migration backend for 'postgres' or 'sqlite', the component extracts the engine via `client.sync_session.kw.get('bind')`. If the lazy client's sessionmaker was constructed without a bind engine (None), migrations cannot proceed and it raises `ValueError` naming the store. It indicates the persistence client was misconfigured at engine-creation time.

Source

Thrown at private_gpt/components/persistence/persistence_component.py:65

                client = LazySQLiteFactory.get_instance(self._settings)

        self._clients[store] = client
        return client

    def _get_migration_backend(
        self,
        store: str,
        client: Any,
    ) -> MigrationBackend:
        match store:
            case "postgres" | "sqlite":
                from private_gpt.components.migrations.backend.sqlalchemy_backend import (
                    SQLAlchemyMigrationBackend,
                )

                engine = client.sync_session.kw.get("bind")
                if engine is None:
                    raise ValueError(
                        f"Cannot resolve SQLAlchemy engine for migration store '{store}'"
                    )
                return SQLAlchemyMigrationBackend(
                    engine=engine,
                    schema_name=self._settings.database.schema_name,
                )
            case _:
                raise ValueError(f"Unsupported store type: {store}")

    def apply_migrations(self) -> None:
        with self._lock:
            if self._migrations_applied:
                logger.info("Migrations already applied in this process; skipping")
                return

            store = self._settings.database.provider
            schema = self._settings.database.schema_name
            logger.info(

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Verify the database client is created through the project's factory (`LazyPostgresFactory.get_instance` / `LazySQLiteFactory.get_instance`) so `sync_session.kw['bind']` is populated
  2. Check database connection settings (URL/host/credentials) so engine creation succeeds instead of silently producing an unbound session
  3. For tests, mock the client with `sync_session.kw = {'bind': create_engine(...)}`
Defensive patterns

Strategy: validation

Validate before calling

client = persistence.get_client(settings.database.provider)
engine = getattr(getattr(client, "sync_session", None), "kw", {}).get("bind")
if engine is None:
    raise ValueError("persistence client session has no bound engine; check DB settings")

Type guard

def client_has_bound_engine(client: Any) -> bool:
    return getattr(getattr(client, "sync_session", None), "kw", {}).get("bind") is not None

Try / catch

try:
    persistence.apply_migrations()
except ValueError as e:
    if "Cannot resolve SQLAlchemy engine" in str(e):
        raise SystemExit("database client misconfigured; check connection settings") from e
    raise

Prevention

When it happens

Trigger: Calling `apply_migrations()`/`revert_migrations()` when `LazyPostgresFactory`/`LazySQLiteFactory` produced a sessionmaker whose `bind` kwarg is None; custom client construction that defers or omits the engine; mocking the client in tests without a bound engine.

Common situations: Custom or partially-initialized database clients; test fakes replacing the persistence client; refactor of the factory changing how the engine is attached to the session.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/011caa82afeac420. Report an issue: GitHub.