crewAIInc/crewAI · error · ValueError

PostgreSQL database error: {e}

Error message

PostgreSQL database error: {e}

What it means

Thrown by PGFileLoader when psycopg raises a database-level Error while executing the query or fetching rows: bad SQL syntax, missing tables/columns, permission denied on a relation, or a query cancelled by statement_timeout. It wraps psycopg3's Error hierarchy into ValueError, preserving the original as __cause__.

Source

Thrown at lib/crewai-tools/src/crewai_tools/rag/loaders/postgres_loader.py:99

                    content = "\n".join(text_parts)

                    if len(content) > 100000:
                        content = content[:100000] + "\n\n[Content truncated...]"

                    return LoaderResult(
                        content=content,
                        metadata={
                            "source": query,
                            "database": connection_params["database"],
                            "row_count": len(rows),
                            "columns": columns,
                        },
                        doc_id=self.generate_doc_id(source_ref=query, content=content),
                    )
            finally:
                connection.close()
        except Error as e:
            raise ValueError(f"PostgreSQL database error: {e}") from e
        except Exception as e:
            raise ValueError(f"Failed to load data from PostgreSQL: {e}") from e

View on GitHub (pinned to 754d7323be)

Solutions

  1. Run the exact query manually with psql or a DB client using the same credentials to see the real error, then fix the SQL.
  2. Confirm the table/view exists in the target database and the URI user has SELECT privilege on it.
  3. For long queries, raise statement_timeout on the role or session, or pre-aggregate the data.
  4. Catch ValueError and inspect e.__cause__ — it is the original psycopg Error with the server's SQLSTATE details.

Example fix

# before
result = loader.load(SourceContent(source="SELECT * FROM user"), metadata=md)  # typo: users

# after
result = loader.load(SourceContent(source="SELECT id, name FROM users LIMIT 1000"), metadata=md)
Defensive patterns

Strategy: validation

Validate before calling

import psycopg

def query_is_valid(conn_string: str, query: str) -> bool:
    with psycopg.connect(conn_string) as conn:
        conn.execute("SELECT 1 FROM (" + query.rstrip(';') + ") q LIMIT 0")
    return True  # raises on bad SQL/permissions

Try / catch

try:
    result = pg_loader.load(src, metadata=md)
except ValueError as e:
    cause = e.__cause__
    if "database error" in str(e).lower():
        log.error("SQL failed: %s", getattr(cause, "diag", None) or cause)

Prevention

When it happens

Trigger: The source string passed to load() is executed verbatim via cursor.execute(query). Typos in SQL, referencing tables that do not exist in the target database, insufficient privileges, or queries that exceed server-side timeouts all surface here. Because the query text is interpolated nowhere, SQL values with parameters (e.g. expecting %s binding) will also fail.

Common situations: Pointing the loader at production where table names differ from staging; using SELECT * on views the service role cannot read; long analytical queries hitting statement_timeout; copy-pasting interactive psql SQL that contains psql-only syntax (\\d, ; handled differently).

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/1ac52c9a45c4700c. Report an issue: GitHub.