ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Fix Agent Failed-to-Fetch Errors
Tutorial

How to Fix Agent Failed-to-Fetch Errors

Diagnose and fix common agent search fetch failures: timeouts, CORS errors, invalid API keys, rate limits, and malformed requests. Working code solutions.

Get Free API KeyAPI Docs

Fix agent failed-to-fetch errors by systematically diagnosing the failure mode and applying the correct fix. The most common causes are timeout errors from slow connections, CORS errors from client-side calls that should be server-side, invalid or expired API keys, rate limit responses that lack retry logic, and malformed request bodies. Each failure mode has a specific diagnostic pattern and fix. This tutorial covers all five and provides drop-in code for each solution.

Prerequisites

  • Python 3.8+ installed
  • requests library installed
  • A Scavio API key from scavio.dev
  • An agent with failing search calls

Walkthrough

Step 1: Diagnose the failure mode

Run a diagnostic that tests each common failure mode to identify the root cause.

Python
import os, requests, time, json

API_KEY = os.environ['SCAVIO_API_KEY']
API_URL = 'https://api.scavio.dev/api/v1/search'

def diagnose(api_key: str = None) -> dict:
    key = api_key or API_KEY
    issues = []
    # Test 1: Basic connectivity
    try:
        resp = requests.post(API_URL,
            headers={'x-api-key': key},
            json={'platform': 'google', 'query': 'test'}, timeout=5)
        if resp.status_code == 401:
            issues.append('INVALID_API_KEY: Check your API key is correct and active')
        elif resp.status_code == 429:
            issues.append('RATE_LIMITED: You are sending too many requests')
        elif resp.status_code >= 500:
            issues.append(f'SERVER_ERROR: Status {resp.status_code}')
        elif resp.status_code == 200:
            data = resp.json()
            if not data.get('organic_results'):
                issues.append('EMPTY_RESULTS: Query returned no results (not an error)')
    except requests.Timeout:
        issues.append('TIMEOUT: Request took >5s, increase timeout or check connection')
    except requests.ConnectionError:
        issues.append('CONNECTION_ERROR: Cannot reach API server')
    except json.JSONDecodeError:
        issues.append('MALFORMED_RESPONSE: Response is not valid JSON')
    if not issues:
        issues.append('NO_ISSUES: API is working correctly')
    return {'issues': issues}

result = diagnose()
for issue in result['issues']:
    print(f'  {issue}')

Step 2: Fix timeout errors

Add proper timeout handling with exponential backoff retry.

Python
def search_with_timeout(query: str, max_retries: int = 3) -> dict:
    """Fix timeout errors with progressive timeout and retry."""
    for attempt in range(max_retries):
        timeout = 10 + (attempt * 5)  # 10s, 15s, 20s
        try:
            resp = requests.post(API_URL,
                headers={'x-api-key': API_KEY},
                json={'platform': 'google', 'query': query},
                timeout=timeout)
            resp.raise_for_status()
            return resp.json()
        except requests.Timeout:
            print(f'Timeout on attempt {attempt + 1} ({timeout}s), retrying...')
            time.sleep(2 ** attempt)
        except requests.RequestException as e:
            print(f'Error on attempt {attempt + 1}: {e}')
            time.sleep(2 ** attempt)
    return {'organic_results': [], 'error': 'All retries exhausted'}

result = search_with_timeout('test query')
print(f"Results: {len(result.get('organic_results', []))}")

Step 3: Fix rate limit errors

Implement rate limit detection and automatic backoff.

Python
class RateLimitedClient:
    """Client with automatic rate limit handling."""
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.min_delay = 0.2  # Minimum delay between requests
        self.last_request = 0

    def search(self, query: str, platform: str = 'google') -> dict:
        # Enforce minimum delay
        elapsed = time.time() - self.last_request
        if elapsed < self.min_delay:
            time.sleep(self.min_delay - elapsed)
        for attempt in range(3):
            self.last_request = time.time()
            resp = requests.post(API_URL,
                headers={'x-api-key': self.api_key},
                json={'platform': platform, 'query': query}, timeout=15)
            if resp.status_code == 429:
                wait = 2 ** (attempt + 1)
                print(f'Rate limited, waiting {wait}s...')
                time.sleep(wait)
                continue
            resp.raise_for_status()
            return resp.json()
        return {'organic_results': [], 'error': 'Rate limit persists'}

client = RateLimitedClient(API_KEY)
result = client.search('test query')
print(f"Results: {len(result.get('organic_results', []))}")

Step 4: Fix malformed request errors

Validate request payload before sending to catch common formatting issues.

Python
VALID_PLATFORMS = ['google', 'amazon', 'youtube', 'walmart', 'reddit']

def validated_search(query: str, platform: str = 'google') -> dict:
    """Search with input validation to prevent malformed requests."""
    # Validate platform
    if platform not in VALID_PLATFORMS:
        print(f'Invalid platform "{platform}". Valid: {VALID_PLATFORMS}')
        platform = 'google'
    # Validate query
    if not query or not query.strip():
        return {'organic_results': [], 'error': 'Empty query'}
    query = query.strip()[:500]  # Trim and limit length
    # Validate API key
    if not API_KEY or len(API_KEY) < 10:
        return {'organic_results': [], 'error': 'Invalid API key format'}
    payload = {'platform': platform, 'query': query}
    try:
        resp = requests.post(API_URL,
            headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
            json=payload, timeout=15)
        resp.raise_for_status()
        return resp.json()
    except Exception as e:
        return {'organic_results': [], 'error': str(e)}

result = validated_search('test query')
print(f"Results: {len(result.get('organic_results', []))}")

Step 5: Build a resilient search wrapper

Combine all fixes into a single resilient search function for your agent.

Python
def resilient_search(query: str, platform: str = 'google') -> dict:
    """Production-grade search with all error handling built in."""
    # Input validation
    if platform not in VALID_PLATFORMS:
        platform = 'google'
    if not query or not query.strip():
        return {'organic_results': [], 'error': 'empty_query'}
    query = query.strip()[:500]
    # Retry with backoff
    for attempt in range(3):
        timeout = 10 + (attempt * 5)
        try:
            resp = requests.post(API_URL,
                headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
                json={'platform': platform, 'query': query},
                timeout=timeout)
            if resp.status_code == 429:
                time.sleep(2 ** (attempt + 1))
                continue
            if resp.status_code == 401:
                return {'organic_results': [], 'error': 'invalid_api_key'}
            resp.raise_for_status()
            return resp.json()
        except requests.Timeout:
            time.sleep(2 ** attempt)
        except requests.ConnectionError:
            time.sleep(2 ** attempt)
        except Exception as e:
            return {'organic_results': [], 'error': str(e)}
    return {'organic_results': [], 'error': 'all_retries_exhausted'}

# Test the resilient wrapper
result = resilient_search('test query')
print(f"Results: {len(result.get('organic_results', []))}")
print(f"Error: {result.get('error', 'none')}")

Python Example

Python
import requests, os, time
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}

def search_safe(query, retries=2):
    for i in range(retries + 1):
        try:
            r = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
                json={'platform': 'google', 'query': query}, timeout=10 + i*5)
            if r.status_code == 429: time.sleep(2**i); continue
            r.raise_for_status()
            return r.json().get('organic_results', [])
        except: time.sleep(2**i)
    return []

print(len(search_safe('test')))

JavaScript Example

JavaScript
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function searchSafe(query, retries = 2) {
  for (let i = 0; i <= retries; i++) {
    try {
      const r = await fetch('https://api.scavio.dev/api/v1/search', {
        method: 'POST', headers: H,
        body: JSON.stringify({platform: 'google', query})
      });
      if (r.status === 429) { await new Promise(r => setTimeout(r, 1000 * 2**i)); continue; }
      return (await r.json()).organic_results || [];
    } catch(e) { await new Promise(r => setTimeout(r, 1000 * 2**i)); }
  }
  return [];
}
searchSafe('test').then(r => console.log(r.length));

Expected Output

JSON
A resilient search wrapper that handles timeouts, rate limits, invalid keys, and malformed requests with automatic retry and clear error reporting.

Related Tutorials

  • How to Fix Hermes v0.12 Search API Fallback
  • How to Build an Agent Search Reliability Layer

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+ installed. requests library installed. A Scavio API key from scavio.dev. An agent with failing search calls. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Related Resources

Best Of

Best Search APIs by Rate Limit Tolerance (2026)

Read more
Use Case

Agent Search Error Handling Patterns

Read more
Best Of

Best APIs for Agent Memory Search Grounding (2026)

Read more
Glossary

Search API Rate Limiting

Read more
Glossary

Search API Provider Landscape (2026)

Read more
Use Case

Hermes Agent Search API Reliability

Read more

Start Building

Diagnose and fix common agent search fetch failures: timeouts, CORS errors, invalid API keys, rate limits, and malformed requests. Working code solutions.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy