zylon-ai/private-gpt · error · ValueError

Generated SQL query is invalid: {error_str}

Error message

Generated SQL query is invalid: {error_str}

What it means

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.

Source

Thrown at private_gpt/components/tabular/database_query_generator.py:932

        for read_dialect in Dialects:
            if read_dialect.value == self._dialect:
                continue

            with contextlib.suppress(ParseError):
                result = "\n".join(
                    sqlglot.transpile(sql, read=read_dialect, write=self._dialect)
                )

                if result:
                    return result

        try:
            return "\n".join(sqlglot.transpile(sql, identity=True, write=self._dialect))
        except ParseError as e:
            error_str = str(e)
            error_str = _ansi_escape.sub("", error_str)
            raise ValueError(f"Generated SQL query is invalid: {error_str}") from e
        except Exception as e:
            raise e

    def _extract_sql_code(self, raw_text: str, transpile_sql: bool = True) -> str:
        """Extract SQL code from the raw text, removing any Markdown formatting.

        LLM usually generates the SQL code wrapped in triple markdown ```
        blocks, sometimes with a "sql" language hint. This function extracts the
        actual SQL code from such formatting.
        """
        # Find the index of the first ``` and last ```
        start_idx = raw_text.find("```")
        end_idx = raw_text.rfind("```")

        clean_code: str

        if start_idx != -1 and end_idx != -1 and start_idx != end_idx:
            # Extract the content between the first and last ```

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Retry generation (optionally feeding the error text back as a correction prompt)
  2. Upgrade/patch sqlglot — parser coverage for vendor syntax improves between releases
  3. 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

Example fix

# before
sql = await generator.generate(question)
# after
try:
    sql = await generator.generate(question)
except ValueError as e:
    logger.warning("generation failed: %s", e)
    sql = await generator.generate(
        question, extra_context=f"Previous attempt was invalid: {e}"
    )
Defensive patterns

Strategy: retry

Validate before calling

import sqlglot
from sqlglot.errors import ParseError

try:
    sqlglot.parse_one(cleaned_sql, read=target_dialect)
except ParseError as e:
    raise ValueError(f"SQL will be rejected downstream: {e}") from e

Try / catch

try:
    return generator._transpile_sql(raw_sql)
except ValueError as e:
    if "invalid" not in str(e):
        raise
    return await generator.generate(
        question, extra_context=f"Fix this SQL: {e}"
    )

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/5110b3f135989a7c. Report an issue: GitHub.