crewAIInc/crewAI · error · RuntimeError

Brave Search API connection failed: {exc}

Error message

Brave Search API connection failed: {exc}

What it means

Raised when the underlying requests.get() to Brave's search endpoint throws requests.ConnectionError — DNS failure, refused connection, TLS handshake problems, or no route to host. The wrapper converts it to RuntimeError with the original exception chained. Unlike HTTP errors, connection errors are not retried by the tool's loop.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/brave_search_tool/base.py:197

    def _make_request(
        self, params: dict[str, Any], *, _max_retries: int = 3
    ) -> dict[str, Any]:
        """Execute an HTTP GET against the Brave Search API with retry logic."""
        last_resp: requests.Response | None = None

        # Retry the request up to _max_retries times
        for attempt in range(_max_retries):
            self._rate_limit()

            try:
                resp = requests.get(
                    self.search_url,
                    headers=self._headers,
                    params=params,
                    timeout=self._timeout,
                )
            except requests.ConnectionError as exc:
                raise RuntimeError(
                    f"Brave Search API connection failed: {exc}"
                ) from exc
            except requests.Timeout as exc:
                raise RuntimeError(
                    f"Brave Search API request timed out after {self._timeout}s: {exc}"
                ) from exc

            logger.debug(
                "Brave Search API request: %s %s -> %d",
                "GET",
                resp.url,
                resp.status_code,
            )

            # Response was OK, return the JSON body
            if resp.ok:
                try:
                    result: dict[str, Any] = resp.json()

View on GitHub (pinned to 754d7323be)

Solutions

  1. Test reachability from the same environment: `curl -v https://api.search.brave.com/res/v1/web/search`.
  2. If a proxy is required, set HTTPS_PROXY/HTTP_PROXY env vars (requests picks them up) or add the domain to the allowlist.
  3. Fix container DNS/egress rules so api.search.brave.com:443 is reachable.
  4. Retry in your own code with backoff for transient connection drops, since the tool does not retry these.

Example fix

# before
results = tool._run("query")

# after
import os
os.environ.setdefault("HTTPS_PROXY", "http://proxy.corp:3128")  # before tool use
results = tool._run("query")
Defensive patterns

Strategy: retry

Validate before calling

import socket

def brave_reachable(host: str = "api.search.brave.com") -> bool:
    try:
        socket.create_connection((host, 443), timeout=5)
        return True
    except OSError:
        return False

Try / catch

except RuntimeError as e:
    if "connection failed" in str(e):
        time.sleep(3)
        result = tool._run(query)  # single retry; persistent failure = network/egress issue
    else:
        raise

Prevention

When it happens

Trigger: No internet or firewall blocking api.search.brave.com; corporate proxy requiring configuration (requests honors HTTP(S)_PROXY env vars); DNS failure in the container; TLS interception breaking the handshake.

Common situations: Corporate networks with mandatory proxies; containers with restricted egress; VPN split-tunnel dropping the API domain; transient ISP-level outages.

Related errors


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