zylon-ai/private-gpt · error · ValueError
Failed to generate SQL query
Error message
Failed to generate SQL query
What it means
Raised after a successful LLM chat call when none of the response content blocks is a TextBlock — i.e. the model returned only non-text content (empty response, tool calls, or an unexpected block type). The SQL extraction path never gets text to parse, so the generator gives up with this generic error instead of returning empty SQL.
Source
Thrown at private_gpt/components/tabular/database_query_generator.py:909
system=ResolvedSystemConfig(
prompt=system_prompt, use_default_prompt=False
),
condensation=CondensationConfig(enabled=False),
sampling_params=sampling_params,
)
)
# find the first text block in the response
for block in response.content:
if isinstance(block, TextBlock):
raw_text = block.text
# despite the instructions, the LLM might
# generate markdown like ```sql ... ```
# so we try to extract the SQL code from it
# remove the prefix and suffix if present
return self._extract_sql_code(raw_text, transpile_sql=False)
raise ValueError("Failed to generate SQL query")
def _transpile_sql(self, sql: str) -> str:
if not self._dialect:
return sql
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:View on GitHub (pinned to 4a030776a3)
Solutions
- Retry the generation request — transient empty completions often succeed on a second attempt
- Free up output tokens: reduce schema size / history so available_tokens for generation is comfortably large
- Inspect response.content types in a debug hook to confirm which block type the model actually returned and adjust prompt/model accordingly
Example fix
# before
result = await generator.generate(...) # raises ValueError
# after
for attempt in range(2):
try:
result = await generator.generate(...)
break
except ValueError as e:
if "Failed to generate SQL" not in str(e) or attempt == 1:
raise Defensive patterns
Strategy: retry
Validate before calling
if not response.content or not any(
hasattr(b, "text") for b in response.content
):
raise ValueError("model returned no text block; retrying") Try / catch
for attempt in range(3):
try:
return await generator.generate(question)
except ValueError as e:
if "Failed to generate SQL" not in str(e) or attempt == 2:
raise
await asyncio.sleep(2**attempt) Prevention
- Keep the generation max_tokens budget comfortably large (shrink schema, not output)
- Log response.content block types when debugging empty generations
When it happens
Trigger: The chat service response contains zero TextBlock entries: model emitted an empty completion, only tool-use blocks, or the response was truncated to nothing by sampling limits (e.g. max_tokens consumed by reasoning).
Common situations: max_tokens budget from schema packing (see the 20% buffer logic) leaving almost nothing for output; a misrouted model that answers with tool calls; provider returning an empty delta list.
Related errors
- The database schema is too long to fit in the model.
- Generated SQL query is invalid: {error_str}
- Failed to describe audio in the message.
- Failed to describe images in the message.
- No items returned from astream_structured_predict
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/67fb14c5450d05d2.
Report an issue: GitHub.