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

  1. 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).
  2. Log the SQL and run it manually to identify the exact syntax/permission problem.
  3. Improve the schema context passed to the LLM (table info, sample rows, dialect note) to reduce invalid SQL generation.
  4. 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

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


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/87c37c7c337bb6b1. Report an issue: GitHub.