infiniflow/ragflow · error · Exception

GitHub search returned no items.

Error message

GitHub search returned no items.

What it means

Raised by the GitHub agent tool when the GitHub Search API response JSON has no 'items' key. GitHub reports rate limits (403/429) and invalid queries (422) through a top-level 'message' field while omitting 'items', so the tool surfaces that message; the literal 'GitHub search returned no items.' only appears when the response has neither key. It replaces what used to be a cryptic KeyError on response['items'].

Source

Thrown at agent/tools/github.py:83

        last_e = ""
        for _ in range(self._param.max_retries + 1):
            if self.check_if_canceled("GitHub processing"):
                return

            try:
                url = "https://api.github.com/search/repositories?q=" + kwargs["query"] + "&sort=stars&order=desc&per_page=" + str(self._param.top_n)
                headers = {"Content-Type": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}
                response = requests.get(url=url, headers=headers, timeout=DEFAULT_TIMEOUT).json()

                if self.check_if_canceled("GitHub processing"):
                    return

                # the github search api reports rate limits (403/429) and invalid
                # queries (422) through a "message" field and omits "items"; surface
                # that instead of raising a cryptic KeyError on the missing key.
                if "items" not in response:
                    raise Exception(response.get("message", "GitHub search returned no items."))

                items = response["items"]
                self._retrieve_chunks(items, get_title=lambda r: r["name"], get_url=lambda r: r["html_url"], get_content=lambda r: str(r["description"]) + "\n stars:" + str(r["watchers"]))
                self.set_output("json", items)
                return self.output("formalized_content")
            except Exception as e:
                if self.check_if_canceled("GitHub processing"):
                    return

                last_e = e
                logging.exception(f"GitHub error: {e}")
                time.sleep(self._param.delay_after_error)

        if last_e:
            self.set_output("_ERROR", str(last_e))
            return f"GitHub error: {last_e}"

        assert False, self.output()

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Check the exception text: 'rate limit exceeded' means wait for the X-RateLimit-Reset window or authenticate the request to raise the limit to 5000/hr (the current code sends no Authorization header).
  2. If it says 'Validation Failed', inspect the query string — remove empty qualifiers, unmatched quotes, or invalid sort/filter syntax.
  3. Add exponential backoff honoring Retry-After on 403/429 instead of the fixed delay_after_error sleep.
  4. Cache results for repeated queries to stay under the 60/hr anonymous quota.

Example fix

// before
headers = {"Content-Type": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}
response = requests.get(url=url, headers=headers, timeout=DEFAULT_TIMEOUT).json()

// after
token = os.environ.get("GITHUB_TOKEN")
headers = {"Content-Type": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"}
if token:
    headers["Authorization"] = f"Bearer {token}"
resp = requests.get(url=url, headers=headers, timeout=DEFAULT_TIMEOUT)
if resp.status_code in (403, 429):
    time.sleep(int(resp.headers.get("Retry-After", "30")))
response = resp.json()
Defensive patterns

Strategy: try-catch

Validate before calling

def safe_github_query(q: str) -> str:
    import re
    q = q.strip().strip('"\'')
    if not q:
        raise ValueError("empty query")
    return q

Try / catch

try:
    out = github_tool._invoke(query=q)
except Exception as e:
    if "rate limit" in str(e).lower():
        wait_for_reset(); rerun()
    elif "items" in str(e) or "no items" in str(e):
        return []  # empty result is not fatal for search flows
    raise

Prevention

When it happens

Trigger: GET https://api.github.com/search/repositories?q=<query>&sort=stars&order=desc&per_page=N returning 403 'rate limit exceeded' (60 req/hr unauthenticated), 422 'Validation Failed' for queries with bad qualifiers (e.g. 'language:' with empty value or stray quotes), or 401 for a revoked token if auth headers are added.

Common situations: Agent workflows that call GitHub search in a loop without a GITHUB_TOKEN, CI runs sharing an office IP that exhausted the anonymous quota, LLM-generated queries containing unescaped quotes or invalid qualifiers like 'repo:' in a repository search, or GitHub secondary rate limiting during bursts.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/c5d5fd739be049ca. Report an issue: GitHub.