tursodatabase/turso · error · ValueError

TursoSyncDialect does not support host/port in URL. The loca

Error message

TursoSyncDialect does not support host/port in URL. The local database path goes after ':///', and remote_url is specified as a query parameter.

What it means

Same validator (_validate_sync_url), second rule: a sqlite+turso_sync URL must be host-less. The local database file path goes after ':///' and the remote endpoint is supplied as a remote_url query parameter (or connect_args). Presence of host or port means the URL was built like a client-server DSN, which the sync dialect does not support.

Source

Thrown at bindings/python/turso/sqlalchemy/dialect.py:386

        return turso.sync

    def connect(self, *cargs, **cparams):
        """Remap sync_url to remote_url for libsql-sqlalchemy compatibility."""

        if "sync_url" in cparams and "remote_url" not in cparams:
            cparams["remote_url"] = cparams.pop("sync_url")
        return super().connect(*cargs, **cparams)

    @staticmethod
    def _validate_sync_url(opts: Dict[str, Any]) -> None:
        """Reject URL components that TursoSyncDialect doesn't support."""
        if opts.get("username") or opts.get("password"):
            raise ValueError(
                "TursoSyncDialect does not support username/password in URL. "
                "Use auth_token query parameter or connect_args instead."
            )
        if opts.get("host") or opts.get("port"):
            raise ValueError(
                "TursoSyncDialect does not support host/port in URL. "
                "The local database path goes after ':///', and remote_url "
                "is specified as a query parameter."
            )

    @staticmethod
    def _extract_sync_params(query_params: Dict[str, str]) -> Dict[str, Any]:
        """Extract and convert sync-specific query parameters into kwargs."""
        kwargs: Dict[str, Any] = {}

        auth_token = query_params.pop("auth_token", None)
        if auth_token:
            kwargs["auth_token"] = auth_token

        client_name = query_params.pop("client_name", None)
        kwargs["client_name"] = client_name or "turso-sqlalchemy"

        long_poll_timeout_ms = query_params.pop("long_poll_timeout_ms", None)

View on GitHub (pinned to bad083fafb)

Solutions

  1. Use the host-less form with query parameters: `sqlite+turso_sync:///local.db?remote_url=libsql://db.example.com&auth_token=...`
  2. Or keep the URL minimal and pass remote_url via connect_args
  3. Remember the path component is a local file path, not a remote database name

Example fix

# before
engine = create_engine("sqlite+turso_sync://db.example.com:443/local.db")

# after
engine = create_engine("sqlite+turso_sync:///local.db?remote_url=libsql://db.example.com")
Defensive patterns

Strategy: validation

Validate before calling

from sqlalchemy.engine import make_url

def lint_turso_sync_url(url: str) -> str:
    u = make_url(url)
    if u.host or u.port:
        raise ValueError(
            "sqlite+turso_sync URLs must be host-less: local path after ':///', "
            "remote endpoint via remote_url query parameter"
        )
    return url

Prevention

When it happens

Trigger: `create_engine("sqlite+turso_sync://db.example.com:443/local.db")` or `sqlite+turso_sync://localhost/db` — treating the dialect like a network driver. Validation runs when the engine first builds connect args.

Common situations: Converting an existing libsql:// or postgres:// connection string by only swapping the scheme; templates that always emit //host/path; developers expecting the sync dialect to connect straight to the remote database.

Related errors


AI-assisted analysis of tursodatabase/turso@bad083fafb (2026-08-16). Data as JSON: /api/errors/25ca270524bec0fb. Report an issue: GitHub.