FoundationAgents/MetaGPT · error · ValueError

Got error from SerpAPI: {res['error']}

Error message

Got error from SerpAPI: {res['error']}

What it means

ValueError from SerperWrapper._process_response: the Serper.dev response JSON contains an 'error' key. Unlike the SerpAPI variant, this wrapper has no tolerated no-results case — any error field raises immediately. Note the message text says 'SerpAPI' even though this is the serper.dev client; that is a copy-paste artifact in the source and does not change the meaning.

Source

Thrown at metagpt/tools/search_engine_serper.py:91

            }
            payloads.append({**self.payload, **_payload})
        return json.dumps(payloads, sort_keys=True)

    def get_headers(self) -> Dict[str, str]:
        headers = {"X-API-KEY": self.api_key, "Content-Type": "application/json"}
        return headers

    @staticmethod
    def _process_response(res: dict, as_string: bool = False) -> str:
        """Process response from SerpAPI."""
        # logger.debug(res)
        focus = ["title", "snippet", "link"]

        def get_focused(x):
            return {i: j for i, j in x.items() if i in focus}

        if "error" in res.keys():
            raise ValueError(f"Got error from SerpAPI: {res['error']}")
        if "answer_box" in res.keys() and "answer" in res["answer_box"].keys():
            toret = res["answer_box"]["answer"]
        elif "answer_box" in res.keys() and "snippet" in res["answer_box"].keys():
            toret = res["answer_box"]["snippet"]
        elif "answer_box" in res.keys() and "snippet_highlighted_words" in res["answer_box"].keys():
            toret = res["answer_box"]["snippet_highlighted_words"][0]
        elif "sports_results" in res.keys() and "game_spotlight" in res["sports_results"].keys():
            toret = res["sports_results"]["game_spotlight"]
        elif "knowledge_graph" in res.keys() and "description" in res["knowledge_graph"].keys():
            toret = res["knowledge_graph"]["description"]
        elif "snippet" in res["organic"][0].keys():
            toret = res["organic"][0]["snippet"]
        else:
            toret = "No good search result found"

        toret_l = []
        if "answer_box" in res.keys() and "snippet" in res["answer_box"].keys():
            toret_l += [get_focused(res["answer_box"])]

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Read the error string inside the message to identify the real cause (key vs credits)
  2. For credit exhaustion, upgrade or wait for quota reset; for keys, update SERPER_API_KEY
  3. Wrap in try/except ValueError with retry/backoff for transient upstream errors

Example fix

# before
res = await serper.run(query)
# after
try:
    res = await serper.run(query)
except ValueError as e:
    # message says 'SerpAPI' but provider is serper.dev; inspect the inner error text
    log.warning("serper.dev error: %s", e)
    raise
Defensive patterns

Strategy: retry

Try / catch

try:
    res = await serper.run(query)
except ValueError as e:
    msg = str(e)
    if "Invalid API key" in msg or "credit" in msg.lower():
        raise  # permanent: fix credentials/plan
    await asyncio.sleep(5)
    res = await serper.run(query)  # transient: retry once

Prevention

When it happens

Trigger: Invalid/expired serper.dev key; exhausted credits (free tier gives ~2500 queries); malformed request payload — anything that makes serper.dev return {'error': ...}.

Common situations: Long batch runs burning through the free tier; stale key after rotation; error message confusingly mentioning 'SerpAPI' leading developers to debug the wrong provider.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/7cff73130f5a63cd. Report an issue: GitHub.