{"record":{"id":"3134cf00f58a6592","repo":"crewAIInc/crewAI","slug":"failed-to-fetch-tables-result","errorCode":null,"errorMessage":"Failed to fetch tables: {result}","messagePattern":"Failed to fetch tables: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/nl2sql/nl2sql_tool.py","lineNumber":281,"sourceCode":"        return self\n\n    def model_post_init(self, __context: Any) -> None:\n        if not SQLALCHEMY_AVAILABLE:\n            raise ImportError(\n                \"sqlalchemy is not installed. Please install it with \"\n                \"`pip install crewai-tools[sqlalchemy]`\"\n            )\n\n        if self.allow_dml:\n            logger.warning(\n                \"NL2SQLTool: allow_dml=True — write operations (INSERT/UPDATE/\"\n                \"DELETE/DROP/…) are permitted. Use with caution.\"\n            )\n\n        data: dict[str, list[dict[str, Any]] | str] = {}\n        result = self._fetch_available_tables()\n        if isinstance(result, str):\n            raise RuntimeError(f\"Failed to fetch tables: {result}\")\n        tables: list[dict[str, Any]] = result\n\n        for table in tables:\n            table_columns = self._fetch_all_available_columns(table[\"table_name\"])\n            data[f\"{table['table_name']}_columns\"] = table_columns\n\n        self.tables = tables\n        self.columns = data\n\n    # Query validation\n\n    def _validate_query(self, sql_query: str) -> None:\n        \"\"\"Raise ValueError if *sql_query* is not permitted under the current config.\n\n        Splits the query on semicolons and validates each statement\n        independently.  When ``allow_dml=False`` (the default), multi-statement\n        queries are rejected outright to prevent ``SELECT 1; DROP TABLE users``\n        style bypasses.  When ``allow_dml=True`` every statement is checked and","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/nl2sql/nl2sql_tool.py#L263-L299","documentation":"NL2SQLTool's model_post_init calls _fetch_available_tables() to introspect the database schema at construction time; that helper returns a string (an error message) instead of a table list when SQLAlchemy cannot read the catalog. When the result is a str, the tool raises RuntimeError wrapping that message. So the real cause (bad URI, unreachable server, permissions) is inside {result}.","triggerScenarios":"Instantiating NL2SQLTool(db_uri=...) when: the DB server is down or unreachable, the URI scheme/driver is malformed or its driver (e.g. psycopg2, pymysql) is missing, credentials are wrong, or the user has no permission to read information_schema/pg_catalog.","commonSituations":"Typos in the db_uri (wrong port, missing dialect prefix like postgresql+psycopg2://), running against a local SQLite file path that does not exist, Docker container DB not yet started when the tool is constructed, or a misquoted password with special characters in the URI.","solutions":["Read the {result} text inside the RuntimeError message — it contains the underlying SQLAlchemy/DBAPI error; fix that root cause first.","Verify connectivity with the same URI from a plain SQLAlchemy engine: sqlalchemy.create_engine(uri).connect().","Check the URI format, e.g. postgresql+psycopg2://user:pass@host:5432/dbname, and URL-encode special characters in the password.","Install the missing DB driver if the message mentions one (pip install psycopg2-binary / pymysql / cx_Oracle).","Ensure the DB user can query the catalog (information_schema.tables / pg_catalog)."],"exampleFix":"# before\nNL2SQLTool(db_uri=\"postgres://user:pass@localhost:5432/db\")\n\n# after\nNL2SQLTool(db_uri=\"postgresql+psycopg2://user:p%40ss@localhost:5432/db\")","handlingStrategy":"try-catch","validationCode":"from sqlalchemy import create_engine, text\n\ndef db_reachable(db_uri: str) -> tuple[bool, str]:\n    try:\n        eng = create_engine(db_uri)\n        with eng.connect() as c:\n            c.execute(text(\"SELECT 1\"))\n        return True, \"\"\n    except Exception as e:\n        return False, str(e)\n\nok, err = db_reachable(uri)\nif not ok:\n    raise SystemExit(f\"db_uri not usable: {err}\")","typeGuard":"def is_valid_db_uri(uri: str) -> bool:\n    try:\n        from sqlalchemy.engine import make_url\n        make_url(uri)\n        return True\n    except Exception:\n        return False","tryCatchPattern":"try:\n    tool = NL2SQLTool(db_uri=uri)\nexcept RuntimeError as e:\n    # message embeds the underlying SQLAlchemy error\n    raise SystemExit(f\"NL2SQLTool init failed: {e}\") from e","preventionTips":["Validate db_uri with sqlalchemy.engine.make_url before constructing the tool.","Smoke-test connectivity with create_engine(uri).connect() in startup checks.","Fail fast at app start rather than constructing NL2SQLTool lazily inside agent runs.","URL-encode passwords containing @ : / characters."],"tags":["nl2sql","database","sqlalchemy","connection","startup"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}