run-llama/llama_index · error · NotImplementedError
Statement {command!r} is invalid SQL.\nError: {exc.orig}
Error message
Statement {command!r} is invalid SQL.\nError: {exc.orig} What it means
SQLWrapper.run_sql() (called by SQLTableRetrieverQueryEngine / NLSQLRetriever when executing model-generated SQL) wraps SQLAlchemy ProgrammingError and OperationalError in NotImplementedError, echoing the offending statement and the driver's original error. Despite the exception type, it means 'this SQL statement failed to execute' - usually invalid SQL produced by the LLM, a missing table/column, or a permissions problem.
Source
Thrown at llama-index-core/llama_index/core/utilities/sql_wrapper.py:262
_replace,
command,
flags=re.IGNORECASE,
)
def run_sql(self, command: str) -> Tuple[str, Dict]:
"""
Execute a SQL statement and return a string representing the results.
If the statement returns rows, a string of the results is returned.
If the statement returns no rows, an empty string is returned.
"""
with self._engine.begin() as connection:
try:
if self._schema:
command = self._add_schema_prefix(command)
cursor = connection.execute(text(command))
except (ProgrammingError, OperationalError) as exc:
raise NotImplementedError(
f"Statement {command!r} is invalid SQL.\nError: {exc.orig}"
) from exc
if cursor.returns_rows:
result = cursor.fetchall()
# truncate the results to the max string length
# we can't use str(result) directly because it automatically truncates long strings
truncated_results = []
for row in result:
# truncate each column, then convert the row to a tuple
truncated_row = tuple(
self.truncate_word(column, length=self._max_string_length)
for column in row
)
truncated_results.append(truncated_row)
return str(truncated_results), {
"result": truncated_results,
"col_keys": list(cursor.keys()),
}View on GitHub (pinned to afd0fef371)
Solutions
- Catch the exception and re-prompt the agent with the error text plus get_table_info() output so the model can self-correct (the standard self-correcting SQL agent pattern).
- Log the SQL and run it manually to identify the exact syntax/permission problem.
- Improve the schema context passed to the LLM (table info, sample rows, dialect note) to reduce invalid SQL generation.
- If the error is permissions-related, grant the DB user access to the referenced tables.
Example fix
# before (agent crashes on bad LLM SQL)
response = query_engine.query('how many users signed up last week?')
# after (self-correcting retry)
from llama_index.core.utilities.sql_wrapper import SQLWrapper
try:
response = query_engine.query(q)
except NotImplementedError as e:
corrected = agent.chat(
f'This SQL failed: {e}. Schema:\n{db.get_table_info()}\nRewrite and answer: {q}'
) Defensive patterns
Strategy: try-catch
Validate before calling
import sqlglot
def sql_is_parseable(command: str, dialect: str = 'sqlite') -> bool:
try:
sqlglot.parse_one(command, read=dialect)
return True
except sqlglot.errors.ParseError:
return False
# guard LLM output before execution:
# if not sql_is_parseable(sql): re-prompt the model Try / catch
try:
result = db.run_sql(sql)
except NotImplementedError as e:
# feed the error back to the LLM for self-correction
sql = agent.chat(
f'SQL failed with: {e}\nSchema:\n{db.get_table_info()}\nRewrite the SQL.'
)
result = db.run_sql(sql) Prevention
- Wrap every query_engine.query()/run_sql call in try/except NotImplementedError with a re-prompt loop (cap retries).
- Include get_table_info() and the SQL dialect in the prompt to reduce invalid SQL.
- Use a read-only DB user so bad LLM SQL cannot mutate data.
- Parse-check generated SQL with sqlglot before executing when the model is unreliable.
When it happens
Trigger: A text-to-SQL query engine executing an LLM-generated statement with wrong syntax, referencing include-filtered tables, or hitting dialect-specific errors (e.g. quoting, functions unsupported by SQLite). The raise happens inside engine.begin() so the transaction rolls back.
Common situations: Agents running NLSQLRetriever/SQLTableRetrieverQueryEngine against strict dialects (SQLite, BigQuery); schemas where some tables were excluded via include_tables but the model still references them; models confusing dialects (MySQL backticks on Postgres).
Related errors
- Cannot specify both include_tables and ignore_tables
- include_tables {missing_tables} not found in database
- ignore_tables {missing_tables} not found in database
- sql_database must be provided.
- table_name must be specified
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/87c37c7c337bb6b1.
Report an issue: GitHub.