{"record":{"id":"5110b3f135989a7c","repo":"zylon-ai/private-gpt","slug":"generated-sql-query-is-invalid-error-str","errorCode":null,"errorMessage":"Generated SQL query is invalid: {error_str}","messagePattern":"Generated SQL query is invalid: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/components/tabular/database_query_generator.py","lineNumber":932,"sourceCode":"\n        for read_dialect in Dialects:\n            if read_dialect.value == self._dialect:\n                continue\n\n            with contextlib.suppress(ParseError):\n                result = \"\\n\".join(\n                    sqlglot.transpile(sql, read=read_dialect, write=self._dialect)\n                )\n\n                if result:\n                    return result\n\n        try:\n            return \"\\n\".join(sqlglot.transpile(sql, identity=True, write=self._dialect))\n        except ParseError as e:\n            error_str = str(e)\n            error_str = _ansi_escape.sub(\"\", error_str)\n            raise ValueError(f\"Generated SQL query is invalid: {error_str}\") from e\n        except Exception as e:\n            raise e\n\n    def _extract_sql_code(self, raw_text: str, transpile_sql: bool = True) -> str:\n        \"\"\"Extract SQL code from the raw text, removing any Markdown formatting.\n\n        LLM usually generates the SQL code wrapped in triple markdown ```\n        blocks, sometimes with a \"sql\" language hint. This function extracts the\n        actual SQL code from such formatting.\n        \"\"\"\n        # Find the index of the first ``` and last ```\n        start_idx = raw_text.find(\"```\")\n        end_idx = raw_text.rfind(\"```\")\n\n        clean_code: str\n\n        if start_idx != -1 and end_idx != -1 and start_idx != end_idx:\n            # Extract the content between the first and last ```","sourceCodeStart":914,"sourceCodeEnd":950,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/components/tabular/database_query_generator.py#L914-L950","documentation":"Raised by _transpile_sql as a last resort: the LLM-generated SQL could not be parsed by sqlglot in the target dialect. The code first tries transpiling from every other dialect into the configured one; only when all attempts fail does it re-attempt with identity=True and raise this ValueError, embedding the ANSI-stripped sqlglot ParseError text. The original ParseError is chained.","triggerScenarios":"The model emits SQL that is syntactically invalid or mixes dialects in ways sqlglot cannot reconcile — unterminated strings, hallucinated vendor syntax, markdown remnants that survived extraction, or comments glued to code.","commonSituations":"Small models producing near-SQL text; extraction of ```sql fences cutting a statement in half; hallucinated functions like STRING_SPLIT in the wrong dialect; version drift between the model's SQL habits and the pinned sqlglot parser.","solutions":["Retry generation (optionally feeding the error text back as a correction prompt)","Upgrade/patch sqlglot — parser coverage for vendor syntax improves between releases","Use a stronger model or a tighter system prompt constraining output to the target dialect, and log raw_text alongside the error to spot extraction bugs"],"exampleFix":"# before\nsql = await generator.generate(question)\n# after\ntry:\n    sql = await generator.generate(question)\nexcept ValueError as e:\n    logger.warning(\"generation failed: %s\", e)\n    sql = await generator.generate(\n        question, extra_context=f\"Previous attempt was invalid: {e}\"\n    )","handlingStrategy":"retry","validationCode":"import sqlglot\nfrom sqlglot.errors import ParseError\n\ntry:\n    sqlglot.parse_one(cleaned_sql, read=target_dialect)\nexcept ParseError as e:\n    raise ValueError(f\"SQL will be rejected downstream: {e}\") from e","typeGuard":null,"tryCatchPattern":"try:\n    return generator._transpile_sql(raw_sql)\nexcept ValueError as e:\n    if \"invalid\" not in str(e):\n        raise\n    return await generator.generate(\n        question, extra_context=f\"Fix this SQL: {e}\"\n    )","preventionTips":["Feed the parser error back into a correction retry before giving up","Keep sqlglot updated for better vendor-dialect coverage","Constrain prompts to the target dialect to reduce cross-dialect SQL"],"tags":["database","text-to-sql","sqlglot","parse-error","llm"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}