{"record":{"id":"f5889e3a52dc2358","repo":"tursodatabase/turso","slug":"tursosyncdialect-does-not-support-username-passwor","errorCode":null,"errorMessage":"TursoSyncDialect does not support username/password in URL. Use auth_token query parameter or connect_args instead.","messagePattern":"TursoSyncDialect does not support username/password in URL\\. Use auth_token query parameter or connect_args instead\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"bindings/python/turso/sqlalchemy/dialect.py","lineNumber":381,"sourceCode":"    @classmethod\n    def import_dbapi(cls):\n        \"\"\"Import the turso.sync module as DBAPI.\"\"\"\n        import turso.sync\n\n        return turso.sync\n\n    def connect(self, *cargs, **cparams):\n        \"\"\"Remap sync_url to remote_url for libsql-sqlalchemy compatibility.\"\"\"\n\n        if \"sync_url\" in cparams and \"remote_url\" not in cparams:\n            cparams[\"remote_url\"] = cparams.pop(\"sync_url\")\n        return super().connect(*cargs, **cparams)\n\n    @staticmethod\n    def _validate_sync_url(opts: Dict[str, Any]) -> None:\n        \"\"\"Reject URL components that TursoSyncDialect doesn't support.\"\"\"\n        if opts.get(\"username\") or opts.get(\"password\"):\n            raise ValueError(\n                \"TursoSyncDialect does not support username/password in URL. \"\n                \"Use auth_token query parameter or connect_args instead.\"\n            )\n        if opts.get(\"host\") or opts.get(\"port\"):\n            raise ValueError(\n                \"TursoSyncDialect does not support host/port in URL. \"\n                \"The local database path goes after ':///', and remote_url \"\n                \"is specified as a query parameter.\"\n            )\n\n    @staticmethod\n    def _extract_sync_params(query_params: Dict[str, str]) -> Dict[str, Any]:\n        \"\"\"Extract and convert sync-specific query parameters into kwargs.\"\"\"\n        kwargs: Dict[str, Any] = {}\n\n        auth_token = query_params.pop(\"auth_token\", None)\n        if auth_token:\n            kwargs[\"auth_token\"] = auth_token","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/tursodatabase/turso/blob/bad083fafbefdeae9a42ec19bdaaad8918dcf411/bindings/python/turso/sqlalchemy/dialect.py#L363-L399","documentation":"TursoSyncDialect._validate_sync_url inspects the components SQLAlchemy parsed out of the URL and rejects URLs containing username or password. The sync driver authenticates with a bearer auth_token, not HTTP basic-auth userinfo, so credentials embedded as sqlite+turso_sync://user:pass@/... are a configuration mistake the dialect refuses early with directions to the supported mechanism.","triggerScenarios":"`create_engine(\"sqlite+turso_sync://user:secret@/local.db\")` or any URL copied from a libsql/https endpoint with embedded credentials, then engine.connect() (validation runs in create_connect_args).","commonSituations":"Porting connection strings from postgres/mysql-style URLs; pasting a libsql:// URL with user:pass into the SQLAlchemy DSN; secret managers templating credentials into the userinfo slot.","solutions":["Move the token to the query string: `sqlite+turso_sync:///local.db?auth_token=<token>`","Or pass it out-of-band: `create_engine(\"sqlite+turso_sync:///local.db\", connect_args={\"auth_token\": token})` — better for secrets, keeps them out of logs","Strip userinfo when generating URLs programmatically"],"exampleFix":"# before\nengine = create_engine(\"sqlite+turso_sync://user:secret@/local.db\")\n\n# after\nengine = create_engine(\n    \"sqlite+turso_sync:///local.db\",\n    connect_args={\"remote_url\": \"libsql://db.example.com\", \"auth_token\": \"secret\"},\n)","handlingStrategy":"validation","validationCode":"from sqlalchemy.engine import make_url\n\ndef lint_turso_sync_url(url: str) -> str:\n    u = make_url(url)\n    if u.username or u.password:\n        raise ValueError(\n            \"credentials do not belong in the URL; pass auth_token as a query param or connect_args\"\n        )\n    return url","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never template user:pass into a sqlite+turso_sync URL — the dialect authenticates with a bearer token","Prefer connect_args={\"auth_token\": ...} so secrets stay out of URLs and logs","Lint generated URLs with make_url() before create_engine() in config validation"],"tags":["python","sqlalchemy","connection-url","auth","credentials"],"backgroundTag":"unsupported-url-credentials","analyzedSha":"bad083fafbefdeae9a42ec19bdaaad8918dcf411","analyzedAt":"2026-08-16T23:12:11.798Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}