crewAIInc/crewAI · error · ValueError
filter_by and filter_value must be provided together.
Error message
filter_by and filter_value must be provided together.
What it means
DB2ToolSchema._validate_pair uses XOR ((filter_by is None) ^ (filter_value is None)) to enforce that the metadata filter is supplied as a complete pair. Providing exactly one of the two — a column without a value, or a value without a column — raises ValueError at Pydantic validation time. Both or neither must be present for the WHERE clause to be well-formed.
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/db2_search_tool/db2_search_tool.py:58
description=(
"Column name used for metadata filtering. "
"Must be used together with filter_value."
),
)
filter_value: Any | None = Field(
default=None,
description=(
"Value used for metadata filtering. Must be used together with filter_by."
),
)
@model_validator(mode="after")
def _validate_filter_pair(self) -> DB2ToolSchema:
if self.filter_by is not None and not self.filter_by.strip():
raise ValueError("filter_by must be a non-empty column name.")
if (self.filter_by is None) ^ (self.filter_value is None):
raise ValueError("filter_by and filter_value must be provided together.")
return self
class DB2VectorSearchTool(BaseTool):
"""
Fortified IBM DB2 Vector Search Tool.
Includes SQL injection protection, dynamic relational support, and type-safe serialization.
"""
model_config = ConfigDict(arbitrary_types_allowed=True)
name: str = "DB2VectorSearchTool"
description: str = "Search IBM DB2 vector database for relevant documents. Uses a custom embedding function if supplied, otherwise OpenAI embeddings."
args_schema: type[BaseModel] = DB2ToolSchema
# Internal Whitelist for distance metrics to prevent SQL injection
# Aligned with Db2 VECTOR_DISTANCE API:
# https://www.ibm.com/docs/en/db2/12.1.x?topic=functions-vector-distanceView on GitHub (pinned to 754d7323be)
Solutions
- Supply both together: filter_by='department', filter_value='sales'.
- Or remove both to run an unfiltered vector search.
- Add a wrapper assertion: (filter_by is None) == (filter_value is None) before invoking the tool.
Example fix
# before tool._run(query='Q3 revenue', filter_by='department') # after tool._run(query='Q3 revenue', filter_by='department', filter_value='finance')
Defensive patterns
Strategy: validation
Validate before calling
def build_filter_kwargs(filter_by: str | None, filter_value) -> dict:
if (filter_by is None) != (filter_value is None):
raise ValueError('filter_by and filter_value must be provided together')
return {} if filter_by is None else {'filter_by': filter_by, 'filter_value': filter_value} Type guard
def is_complete_filter_pair(kw: dict) -> bool:
return (kw.get('filter_by') is None) == (kw.get('filter_value') is None) Try / catch
try:
tool._run(query=q, **kw)
except ValidationError as e:
if 'provided together' in str(e):
kw.pop('filter_by', None); kw.pop('filter_value', None)
tool._run(query=q, **kw) # retry unfiltered
else:
raise Prevention
- Construct filter kwargs through one helper that enforces the pair invariant.
- Omit keys entirely rather than sending None when no filter is wanted.
- Add a unit test asserting XOR inputs raise early in your own code.
When it happens
Trigger: tool._run(query='...', filter_by='department') with no filter_value; or filter_value='sales' with no filter_by; agent JSON that includes one field and drops the other; kwargs built by merging dicts where one key gets overwritten.
Common situations: LLM tool calls that fill the filter column from the prompt but leave the value blank (or vice versa); refactors where filter_value is accidentally renamed; optional-argument handling that defaults one side to None and the other to ''.
Related errors
- filter_by must be a non-empty column name.
- return_columns cannot be empty. At least one column must be
- Invalid distance metric: {metric}
- Missing required input '{name}'{suffix}
- Invalid input '{location}': {error.get('msg')}
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/6f36aadf1625eacf.
Report an issue: GitHub.