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
- 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).
- If it says 'Validation Failed', inspect the query string — remove empty qualifiers, unmatched quotes, or invalid sort/filter syntax.
- Add exponential backoff honoring Retry-After on 403/429 instead of the fixed delay_after_error sleep.
- 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
- Authenticate GitHub API calls with a token to lift the 60/hr anonymous limit to 5000/hr.
- Honor Retry-After / X-RateLimit-Reset instead of fixed sleeps.
- Sanitize LLM-generated queries (strip quotes, drop empty qualifiers) before they reach the API.
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
- SerpApi returned no organic_results.
- Failed to fetch github user info: {e}
- 'str' object has no attribute 'get'
- Validation failed due to GitHub rate-limits being exceeded.
- Request failed
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/c5d5fd739be049ca.
Report an issue: GitHub.