crewAIInc/crewAI · error · ValueError
MySQL table_name must be a valid table identifier or schema.
Error message
MySQL table_name must be a valid table identifier or schema.table identifier
What it means
MySQLSearchTool quotes the user-supplied table name into backticks after validating each dot-separated part against ^[A-Za-z_][A-Za-z0-9_$]*$. This ValueError fires when the name is not a bare identifier or schema.table: more than one dot, empty part, leading digit, spaces, hyphens, backticks, or other characters. It is primarily a SQL-injection guard that rejects anything it cannot safely quote.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/mysql_search_tool/mysql_search_tool.py:22
from pydantic import BaseModel, Field
from crewai_tools.rag.data_types import DataType
from crewai_tools.tools.rag.rag_tool import RagTool
_MYSQL_IDENTIFIER_PATTERN = re.compile(r"^[A-Za-z_][A-Za-z0-9_$]*$")
def _quote_mysql_table_name(table_name: str) -> str:
identifier_parts = table_name.split(".")
if (
not identifier_parts
or len(identifier_parts) > 2
or any(
not _MYSQL_IDENTIFIER_PATTERN.fullmatch(part) for part in identifier_parts
)
):
raise ValueError(
"MySQL table_name must be a valid table identifier or schema.table "
"identifier"
)
return ".".join(f"`{part}`" for part in identifier_parts)
class MySQLSearchToolSchema(BaseModel):
"""Input for MySQLSearchTool."""
search_query: str = Field(
...,
description="Mandatory semantic search query you want to use to search the database's content",
)
class MySQLSearchTool(RagTool):
name: str = "Search a database's table content"View on GitHub (pinned to 754d7323be)
Solutions
- Pass a bare identifier: MySQLSearchTool(table_name="users") or "schema.users"
- For names with special characters, the validator forbids them — rename the table or use a view with a safe name
- Strip accidental whitespace: table_name.strip() before constructing the tool
Example fix
# before tool = MySQLSearchTool(table_name="my-db.my-table") # ValueError # after tool = MySQLSearchTool(table_name="my_db.my_table") # underscore, one dot max
Defensive patterns
Strategy: validation
Validate before calling
import re
_MYSQL_IDENT = re.compile(r"^[A-Za-z_][A-Za-z0-9_$]*$")
def valid_mysql_table_name(name: str) -> bool:
parts = name.strip().split(".")
return 1 <= len(parts) <= 2 and all(_MYSQL_IDENT.fullmatch(p) for p in parts) Type guard
def is_valid_mysql_table_name(name: str) -> bool:
parts = name.strip().split(".")
return 1 <= len(parts) <= 2 and all(
__import__("re").fullmatch(r"[A-Za-z_][A-Za-z0-9_$]*", p) for p in parts
) Try / catch
try:
tool = MySQLSearchTool(table_name=name)
except ValueError as e:
if "valid table identifier" in str(e):
raise ValueError(
f"{name!r} is not schema.table-safe; use bare identifiers only"
) from e
raise Prevention
- Pass bare identifiers only — never pre-quoted or hyphenated names
- Validate user-supplied table names with the same regex before building tools
- Create safe-named views over awkward legacy table names
When it happens
Trigger: Passing table_name="my-table" (hyphen), "db.schema.table" (two dots), "1table" (leading digit), "`users`" (pre-quoted), or "public .users" (spaces); passing a subquery or table name with whitespace/newlines.
Common situations: Table names with hyphens created outside the app; users trying to pre-quote with backticks; copy-pasted names with hidden whitespace; attempts to pass raw SQL fragments.
Related errors
- Invalid data_type: '{raw_data_type}'. Valid values are: 'fil
- Directory does not exist: {source_ref}
- Database URI is required for MySQL loader
- Invalid MySQL URI scheme: {parsed.scheme}
- Database name is required in the URI
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/ee1a8ddd151bf9a7.
Report an issue: GitHub.