crewAIInc/crewAI · error · ValueError

search_query is required

Error message

search_query is required

What it means

SerperDevTool._run raises ValueError("search_query is required") when neither the search_query nor the query keyword argument is truthy. The tool checks kwargs.get("search_query") or kwargs.get("query") and, combined with there being no instance-level default query, an empty/missing query aborts before any request.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/serper_dev_tool/serper_dev_tool.py:324

            if "relatedSearches" in results:
                formatted_results["relatedSearches"] = self._process_related_searches(
                    results["relatedSearches"]
                )

        elif search_type == "news":
            if "news" in results:
                formatted_results["news"] = self._process_news_results(results["news"])

        return formatted_results

    def _run(self, **kwargs: Any) -> FormattedResults:
        """Execute the search operation."""
        search_query: str | None = kwargs.get("search_query") or kwargs.get("query")
        search_type: str = kwargs.get("search_type", self.search_type)
        save_file = kwargs.get("save_file", self.save_file)

        if not search_query:
            raise ValueError("search_query is required")

        results = self._make_api_request(search_query, search_type)

        formatted_results = {
            "searchParameters": {
                "q": search_query,
                "type": search_type,
                **results.get("searchParameters", {}),
            }
        }

        formatted_results.update(self._process_search_results(results, search_type))
        formatted_results["credits"] = results.get("credits", 1)

        if save_file:
            _save_results_to_file(json.dumps(formatted_results, indent=2))

        return formatted_results  # type: ignore[return-value]

View on GitHub (pinned to 754d7323be)

Solutions

  1. Pass a non-empty search string: tool._run(search_query="crewai") (query= is also accepted).
  2. If an agent is producing empty queries, add a description/example to the tool input schema or validate the model output before invoking the tool.
  3. Wrap the call in try/except ValueError to degrade gracefully (return a prompt asking for a query).

Example fix

# before
result = serper_tool._run()

# after
result = serper_tool._run(search_query="latest crewai release")
Defensive patterns

Strategy: validation

Validate before calling

query = (kwargs.get("search_query") or kwargs.get("query") or "").strip()
if not query:
    raise ValueError("A non-empty search_query must be provided")
result = serper_tool._run(search_query=query)

Type guard

def has_search_query(kwargs: dict) -> bool:
    return bool((kwargs.get("search_query") or kwargs.get("query") or "").strip())

Try / catch

try:
    result = serper_tool._run(**kwargs)
except ValueError as e:
    if "search_query is required" in str(e):
        return "Please provide a search query."  # agent re-ask
    raise

Prevention

When it happens

Trigger: Calling tool._run() with no arguments; calling _run(search_query="") or _run(query=None); or an LLM agent producing a tool call that omits the query string.

Common situations: Agent frameworks generating malformed tool arguments (empty string query from the model), or test code invoking the tool without inputs. Very common when the tool schema is bypassed and _run is called directly.

Related errors


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