{"record":{"id":"9d3bd33b1e012316","repo":"zylon-ai/private-gpt","slug":"mysql-connection-requires-mysql-mysql-mysqldb-or","errorCode":null,"errorMessage":"MySQL connection requires mysql, mysql+mysqldb, or mysql+pymysql scheme","messagePattern":"MySQL connection requires mysql, mysql\\+mysqldb, or mysql\\+pymysql scheme","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/tabular/database_query_generator.py","lineNumber":445,"sourceCode":"\n        if self._dialect in [Dialects.TSQL]:\n            # MSSQL specific adjustments\n            if not any(k.lower() == \"encrypt\" for k in params):\n                params[\"Encrypt\"] = [\"yes\" if self.ssl else \"no\"]\n\n            if not any(k.lower() == \"driver\" for k in params):\n                if not parsed.scheme.startswith(\"mssql+pyodbc\"):\n                    raise ValueError(\n                        \"MSSQL connection requires pyodbc scheme when no driver specified\"\n                    )\n                params[\"driver\"] = [\"ODBC Driver 18 for SQL Server\"]\n\n        elif self._dialect in [Dialects.MYSQL]:\n            # MySQL specific adjustments\n            if parsed.scheme == \"mysql\" or parsed.scheme == \"mysql+mysqldb\":\n                parsed = parsed._replace(scheme=\"mysql+pymysql\")\n            elif not parsed.scheme.startswith(\"mysql+pymysql\"):\n                raise ValueError(\n                    \"MySQL connection requires mysql, mysql+mysqldb, or mysql+pymysql scheme\"\n                )\n            if not any(k.lower() == \"charset\" for k in params):\n                params[\"charset\"] = [\"utf8mb4\"]\n\n        flattened = {k: v[0] if len(v) == 1 else v for k, v in params.items()}\n        new_parsed = parsed._replace(query=urlencode(flattened, doseq=True))\n        self.connection_string = str(urlunparse(new_parsed))\n\n    def _check_connection(self) -> str | None:\n        \"\"\"Check if the database connection can be established.\n\n        Returns None if successful, or an error message if failed.\n        \"\"\"\n        try:\n            conn = self._ensure_connected()\n            dialect = classify_dialect(\n                self._engine.dialect.name if self._engine else None","sourceCodeStart":427,"sourceCodeEnd":463,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/tabular/database_query_generator.py#L427-L463","documentation":"Raised while preparing a MySQL connection string: the component normalizes mysql and mysql+mysqldb schemes to mysql+pymysql (because pymysql is the supported driver), and rejects any other scheme such as mysql+asyncpg, mysql+mysqlconnector, or a bare typo. This guarantees the SQLAlchemy engine is always built on pymysql, which the rest of the tabular query path expects.","triggerScenarios":"Supplying a connection string whose scheme is not mysql, mysql+mysqldb, or mysql+pymysql while the dialect resolves to MySQL — e.g. mysql+mysqlconnector://... or mariadb://...","commonSituations":"Reusing a URL written for a different MySQL driver stack; attempting MariaDB URLs; uppercase scheme (MySQL://) which urlparse does not lowercase, failing the exact-match checks.","solutions":["Use mssql-normalized MySQL form: mysql+pymysql://user:pass@host:3306/db","Plain mysql:// or mysql+mysqldb:// also work (auto-rewritten to pymysql)","Lowercase the scheme and double-check for typos like mysql+pymsql"],"exampleFix":"# before\nconnection_string = \"mysql+mysqlconnector://root:pass@db:3306/sakila\"\n# after\nconnection_string = \"mysql+pymysql://root:pass@db:3306/sakila\"","handlingStrategy":"validation","validationCode":"from urllib.parse import urlparse\n\nscheme = urlparse(connection_string).scheme.lower()\nif scheme not in {\"mysql\", \"mysql+mysqldb\", \"mysql+pymysql\"}:\n    raise ValueError(\n        \"MySQL URL scheme must be mysql, mysql+mysqldb, or mysql+pymysql\"\n    )","typeGuard":"def is_valid_mysql_url(conn: str) -> bool:\n    scheme = urlparse(conn).scheme.lower()\n    return scheme in {\"mysql\", \"mysql+mysqldb\", \"mysql+pymysql\"}","tryCatchPattern":null,"preventionTips":["Use mysql+pymysql:// as the canonical scheme (component rewrites to it anyway)","Lowercase schemes and watch for mariadb:// or mysql+asyncpg URLs from other tooling"],"tags":["database","mysql","connection-string","pymysql","configuration"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}