pola-rs/polars · error · TypeError
Unrecognised connection type {qualified_type_name(conn)!r};
Error message
Unrecognised connection type {qualified_type_name(conn)!r}; no 'execute' or 'cursor' method What it means
When read_database initializes a cursor from your object (ConnectionExecutor._cursor_init), it accepts anything with a cursor() method (DBAPI connection) or an execute() method (cursor, SQLAlchemy connection, ADBC handle). An object with neither is treated as an unrecognised connection type and raises TypeError including the qualified class name. This is the type-shape gate before any query runs - the repr in the message tells you exactly what leaked in.
Source
Thrown at py-polars/src/polars/io/database/_executor.py:472
return conn
elif hasattr(conn, "cursor"):
# connection has a dedicated cursor; prefer over direct execute
cursor = (
cast("Cursor", cursor()) if callable(cursor := conn.cursor) else cursor
)
self.can_close_cursor = True
return cursor
elif hasattr(conn, "execute"):
# can execute directly (given cursor, sqlalchemy connection, etc)
return conn
msg = (
f"Unrecognised connection type {qualified_type_name(conn)!r}; no "
"'execute' or 'cursor' method"
)
raise TypeError(msg)
async def _sqlalchemy_async_execute(self, query: TextClause, **options: Any) -> Any:
"""Execute a query using an async SQLAlchemy connection."""
is_session = self._is_alchemy_session(self.cursor)
cursor = self.cursor.begin() if is_session else self.cursor # type: ignore[attr-defined]
# check if connection is already started (eg: user awaited `engine.connect()`);
# if so, use it directly without entering the context manager again
if getattr(cursor, "sync_connection", None) is not None:
return await cursor.execute(query, **options)
async with cursor as conn: # type: ignore[union-attr]
if is_session and not hasattr(conn, "execute"):
conn = conn.session
result = await conn.execute(query, **options)
return result
def _sqlalchemy_setup(View on GitHub (pinned to df599052da)
Solutions
- For connection strings use pl.read_database_uri(query, uri, engine='connectorx')
- For objects, pass a real connection/cursor: engine.connect(), raw DBAPI connect(), or conn.cursor()
- If wrapping drivers, expose an execute() method on your wrapper
Example fix
# before
pl.read_database('SELECT * FROM t', connection='postgresql://user:pw@host/db')
# after - URI goes to read_database_uri
pl.read_database_uri('SELECT * FROM t', 'postgresql://user:pw@host/db')
# after - or pass a live connection object
pl.read_database('SELECT * FROM t', connection=engine.connect()) Defensive patterns
Strategy: type-guard
Validate before calling
def is_connection_like(obj: object) -> bool:
return hasattr(obj, 'cursor') or hasattr(obj, 'execute')
assert is_connection_like(conn), (
'read_database needs a connection/cursor object; '
'use read_database_uri for connection strings'
)
df = pl.read_database(query, connection=conn) Type guard
from typing import TypeGuard
from typing import Any
def is_connection_or_cursor(obj: Any) -> TypeGuard[Any]:
"""Narrow to objects polars' read_database can drive."""
return hasattr(obj, 'cursor') or hasattr(obj, 'execute') Try / catch
try:
df = pl.read_database(query, connection=conn)
except TypeError as err:
if 'Unrecognised connection type' in str(err):
df = pl.read_database_uri(query, conn) if isinstance(conn, str) else None
if df is None:
raise
else:
raise Prevention
- Route connection strings to read_database_uri and live objects to read_database - enforce with a dispatcher helper
- Do not pass Engines or Sessions; pass engine.connect() or cursor objects
- When wrapping drivers in your own classes, expose execute()
When it happens
Trigger: pl.read_database('SELECT 1', connection='postgresql://user:pw@host/db') (URI string instead of an object); passing a config dict, an Engine (has neither cursor nor execute), or an ORM Session-like wrapper without execute; passing None.
Common situations: Confusing read_database (wants a live connection/cursor object) with read_database_uri (wants a URI string); passing SQLAlchemy create_engine(...) result directly; factory functions returning a wrapper class that hides .execute().
Related errors
- invalid input for `exclude`\n\nExpected one or more `str` or
- Series name must be a string
- the truth value of a Series is ambiguous Here are some thin
- cannot select columns using key of type {qualified_type_name
- cannot select rows using key of type {qualified_type_name(ke
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/92c784674dd94537.
Report an issue: GitHub.