{"record":{"id":"7d6fbfbb6f077820","repo":"tursodatabase/turso","slug":"cannot-get-raw-connection-from-sqlalchemy-connecti","errorCode":null,"errorMessage":"Cannot get raw connection from SQLAlchemy connection","messagePattern":"Cannot get raw connection from SQLAlchemy connection","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"bindings/python/turso/sqlalchemy/dialect.py","lineNumber":527,"sourceCode":"            sync.push()\n\n    Args:\n        connection: A SQLAlchemy Connection object\n\n    Returns:\n        The underlying turso.sync.ConnectionSync object\n\n    Raises:\n        TypeError: If the connection is not a Turso sync connection\n    \"\"\"\n    from turso.lib_sync import ConnectionSync\n\n    # Get the raw DBAPI connection\n    # SQLAlchemy 2.0: connection.connection.dbapi_connection\n    # SQLAlchemy 1.4: connection.connection\n    raw_conn = getattr(connection, \"connection\", None)\n    if raw_conn is None:\n        raise TypeError(\"Cannot get raw connection from SQLAlchemy connection\")\n\n    # Handle SQLAlchemy 2.0 pooled connection wrapper\n    dbapi_conn = getattr(raw_conn, \"dbapi_connection\", raw_conn)\n\n    if not isinstance(dbapi_conn, ConnectionSync):\n        raise TypeError(\n            f\"Expected turso.sync.ConnectionSync, got {type(dbapi_conn).__name__}. \"\n            \"This function only works with sqlite+turso_sync:// connections.\"\n        )\n\n    return dbapi_conn\n","sourceCodeStart":509,"sourceCodeEnd":539,"githubUrl":"https://github.com/tursodatabase/turso/blob/244cde92a7df7f9b8b8b7a4075c35a12977e303e/bindings/python/turso/sqlalchemy/dialect.py#L509-L539","documentation":"get_sync_connection(connection) unwraps a SQLAlchemy Connection in two steps: first connection.connection, then the dbapi_connection attribute on SQLAlchemy 2.0's pooled-connection wrapper. If the object has no .connection attribute at all (getattr returns None), the function raises TypeError('Cannot get raw connection from SQLAlchemy connection') - the argument simply is not a live SQLAlchemy Connection.","triggerScenarios":"Passing an Engine instead of a Connection (engine.connection does not exist); passing a Session, a raw string, a ConnectionSync that is already unwrapped, or a test double.","commonSituations":"Refactoring code that used to call engine.connect() inline; helpers meant to accept 'a connection-like thing'; tests passing mocks.","solutions":["Pass a Connection: with engine.connect() as conn: get_sync_connection(conn)","Pull the connection from a Session via session.connection() when using the ORM","Do not feed raw turso connections or engines into this helper"],"exampleFix":"# before\nraw = get_sync_connection(engine)  # TypeError\n\n# after\nwith engine.connect() as conn:\n    raw = get_sync_connection(conn)","handlingStrategy":"type-guard","validationCode":"def is_sqlalchemy_connection(obj) -> bool:\n    return hasattr(obj, \"connection\")","typeGuard":"def is_sqlalchemy_connection(obj) -> bool:\n    # A live SQLAlchemy Connection exposes .connection; engines and strings do not.\n    return hasattr(obj, \"connection\")","tryCatchPattern":"try:\n    raw = get_sync_connection(conn)\nexcept TypeError as e:\n    if \"raw connection\" in str(e):\n        raise TypeError(\"Pass engine.connect()'s result, not the engine\") from e\n    raise","preventionTips":["Always call the helper inside 'with engine.connect() as conn:'","Type helper parameters as sqlalchemy.Connection, not object","Unwrap once at the boundary and pass the ConnectionSync down"],"tags":["python","sqlalchemy","type-error","helper-api"],"backgroundTag":"invalid-argument-value","analyzedSha":"244cde92a7df7f9b8b8b7a4075c35a12977e303e","analyzedAt":"2026-08-20T07:02:18.389Z","contentChangedAt":"2026-08-20T07:02:18.389Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}