pola-rs/polars · error · ValueError
string URI is invalid here; call `read_database_uri` instead
Error message
string URI is invalid here; call `read_database_uri` instead
What it means
Raised by read_database() when the connection argument is a string containing '://', i.e. a URI. read_database expects a live connection/cursor object; URI-based access has a dedicated function, read_database_uri, so polars redirects you instead of trying to interpret the URI as a connection.
Source
Thrown at py-polars/src/polars/io/database/functions.py:256
... query="SELECT * FROM test",
... url="http://localhost:8000",
... )
... ) # doctest: +SKIP
""" # noqa: W505
if isinstance(connection, str):
# check for odbc connection string
if re.search(r"\bdriver\s*=\s*{[^}]+?}", connection, re.IGNORECASE):
_ = import_optional(
module_name="arrow_odbc",
err_prefix="use of ODBC connection string requires the",
err_suffix="package",
)
connection = ODBCCursorProxy(connection)
elif "://" in connection:
# otherwise looks like a mistaken call to read_database_uri
msg = "string URI is invalid here; call `read_database_uri` instead"
raise ValueError(msg)
else:
msg = "unable to identify string connection as valid ODBC (no driver)"
raise ValueError(msg)
# adbc_driver_manager must be >= 1.7.0 to support passing Python sequences into
# parameterised queries (via execute_options) without PyArrow installed
if (
execute_options is not None
and not _PYARROW_AVAILABLE
and type(connection).__module__.split(".", 1)[0].startswith("adbc")
):
adbc_version_no_pyarrow_required = "1.7.0"
adbc_driver_manager = import_optional("adbc_driver_manager")
adbc_str_version = getattr(adbc_driver_manager, "__version__", "0.0")
if not parse_version(adbc_str_version) >= parse_version(
adbc_version_no_pyarrow_required
):
msg = (View on GitHub (pinned to df599052da)
Solutions
- Use pl.read_database_uri(query, uri) for string URIs (with engine='connectorx' or 'adbc')
- Or keep read_database and pass a real connection object, e.g. sqlalchemy.create_engine(uri).connect()
Example fix
# before
pl.read_database("SELECT * FROM t", "postgresql://user:pw@host/db")
# after
pl.read_database_uri("SELECT * FROM t", "postgresql://user:pw@host/db") Defensive patterns
Strategy: validation
Validate before calling
def read_any(query: str, conn_or_uri):
if isinstance(conn_or_uri, str) and "://" in conn_or_uri:
return pl.read_database_uri(query, conn_or_uri)
return pl.read_database(query, conn_or_uri) Type guard
def is_connection_uri(value: object) -> bool:
return isinstance(value, str) and "://" in value Prevention
- Keep one helper that routes str-URIs to read_database_uri and objects to read_database
- Name variables conn (object) vs uri (string) to avoid mixups
- Remember ODBC driver strings (driver={...}) are the only strings read_database accepts
When it happens
Trigger: pl.read_database(query, 'postgresql://user:pass@host/db') — passing a URI string where a connection object is required.
Common situations: Confusing the two database entry points (names differ by only a suffix); porting code between them; copy-pasting a connection string from environment variables into the wrong function.
Related errors
- expected connection to be a URI string; found {qualified_typ
- Unrecognised connection type {qualified_type_name(conn)!r};
- cannot return a frame before executing a query
- unable to identify string connection as valid ODBC (no drive
- Event loop stopped before Future completed.
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/0ae3f520d0c5291f.
Report an issue: GitHub.