zylon-ai/private-gpt · error · ValueError
MSSQL connection requires pyodbc scheme when no driver speci
Error message
MSSQL connection requires pyodbc scheme when no driver specified
What it means
Raised while preparing an MSSQL (TSQL dialect) connection string: when the URL has no explicit 'driver' query parameter, the code injects 'ODBC Driver 18 for SQL Server' — but only if the scheme starts with mssql+pyodbc. Any other scheme (mssql, mssql+pymssql, ...) cannot accept an ODBC driver parameter, so the code rejects it rather than building a broken connection string.
Source
Thrown at private_gpt/components/tabular/database_query_generator.py:435
modified_query = f'CALL {proc_name}({params_with_cursor}); FETCH ALL FROM "{cursor_name}";'
return modified_query
return query
def _prepare_connection_string(self) -> None:
parsed = urlparse(self.connection_string)
params = parse_qs(parsed.query, keep_blank_values=True)
if self._dialect in [Dialects.TSQL]:
# MSSQL specific adjustments
if not any(k.lower() == "encrypt" for k in params):
params["Encrypt"] = ["yes" if self.ssl else "no"]
if not any(k.lower() == "driver" for k in params):
if not parsed.scheme.startswith("mssql+pyodbc"):
raise ValueError(
"MSSQL connection requires pyodbc scheme when no driver specified"
)
params["driver"] = ["ODBC Driver 18 for SQL Server"]
elif self._dialect in [Dialects.MYSQL]:
# MySQL specific adjustments
if parsed.scheme == "mysql" or parsed.scheme == "mysql+mysqldb":
parsed = parsed._replace(scheme="mysql+pymysql")
elif not parsed.scheme.startswith("mysql+pymysql"):
raise ValueError(
"MySQL connection requires mysql, mysql+mysqldb, or mysql+pymysql scheme"
)
if not any(k.lower() == "charset" for k in params):
params["charset"] = ["utf8mb4"]
flattened = {k: v[0] if len(v) == 1 else v for k, v in params.items()}
new_parsed = parsed._replace(query=urlencode(flattened, doseq=True))
self.connection_string = str(urlunparse(new_parsed))View on GitHub (pinned to 4a030776a3)
Solutions
- Use the pyodbc scheme: mssql+pyodbc://user:pass@host:1433/db?driver=ODBC+Driver+18+for+SQL+Server
- Or keep your existing mssql:// scheme but add an explicit driver parameter — note non-pyodbc schemes still need the driver to be ODBC-compatible for SQLAlchemy
- URL-encode spaces in the driver value or use + (ODBC+Driver+18+for+SQL+Server)
Example fix
# before
connection_string = "mssql://sa:pass@db:1433/master"
# after
connection_string = (
"mssql+pyodbc://sa:pass@db:1433/master"
"?driver=ODBC+Driver+18+for+SQL+Server&Encrypt=yes"
) Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse, parse_qs
parsed = urlparse(connection_string)
params = parse_qs(parsed.query, keep_blank_values=True)
has_driver = any(k.lower() == "driver" for k in params)
if not has_driver and not parsed.scheme.startswith("mssql+pyodbc"):
raise ValueError(
"MSSQL URL needs ?driver=... or the mssql+pyodbc scheme"
) Type guard
def is_valid_mssql_url(conn: str) -> bool:
p = urlparse(conn)
q = parse_qs(p.query, keep_blank_values=True)
return p.scheme.startswith("mssql+pyodbc") or any(
k.lower() == "driver" for k in q
) Prevention
- Standardize on mssql+pyodbc://…?driver=ODBC+Driver+18+for+SQL+Server in all environments
- URL-encode spaces in driver names (+ or %20)
When it happens
Trigger: Supplying a connection string like mssql://user:pass@host/db or mssql+pymssql://... without a ?driver=... parameter while the dialect resolves to TSQL.
Common situations: Copy-pasting an ADO or pymssql-style URL from another tool; defaulting encrypt/driver handling assumptions from SQL Server docs; switching a generic mssql:// URL into this component without rewriting the scheme.
Related errors
- MySQL connection requires mysql, mysql+mysqldb, or mysql+pym
- Invalid system item in list: {item}
- Unknown condense strategy: {strategy}
- Audio blocks found but no audio-capable LLM provided.
- Code execution provider '{name}' is not registered. Availabl
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/154a839567bc7373.
Report an issue: GitHub.