Error Handling
Understanding and handling API errors
Error Response Format
All API errors follow a consistent JSON format:
{
"error": "Error message describing what went wrong"
}The HTTP status code indicates the error category, and the error message provides specific details.
HTTP Status Codes
Success Codes
200OKRequest successful, data returned
Client Error Codes
400Bad RequestThe request was malformed or contains invalid parameters
Common causes:
- Missing required query parameters
- Invalid ticker_id format
- Malformed request body
404Not FoundThe requested resource does not exist
Common causes:
- Invalid endpoint path
- Ticker not found
- DAO does not exist
429Too Many RequestsRate limit exceeded
Details:
- Limit: 60 requests per minute per IP
- Reset: Wait until the next minute window
Server Error Codes
500Internal Server ErrorAn unexpected error occurred on the server
Common causes:
- RPC connection issues
- Blockchain data unavailable
- Service temporarily down
502Bad GatewayUpstream service (RPC) is unavailable
503Service UnavailableAPI is temporarily unavailable (maintenance or overload)
Common Error Scenarios
Rate Limit Exceeded
When you exceed 60 requests per minute:
{
"error": "Rate limit exceeded. Please try again later."
}Solution:
- Implement Retry Logic
Wait 60 seconds before retrying
- Use Exponential Backoff
Gradually increase wait time between retries
- Cache Responses
Store frequently accessed data locally
Example Implementation:
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.status === 429) {
const waitTime = Math.pow(2, i) * 1000; // Exponential backoff
console.log(`Rate limited. Waiting ${waitTime}ms...`);
await new Promise(resolve => setTimeout(resolve, waitTime));
continue;
}
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
// Usage
const tickers = await fetchWithRetry('https://your-api-domain.com/api/tickers');import time
import requests
from typing import Optional, Dict
def fetch_with_retry(url: str, max_retries: int = 3) -> Optional[Dict]:
for i in range(max_retries):
try:
response = requests.get(url)
if response.status_code == 429:
wait_time = (2 ** i) * 1 # Exponential backoff
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
continue
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
if i == max_retries - 1:
raise e
time.sleep(i + 1)
return None
# Usage
tickers = fetch_with_retry('https://your-api-domain.com/api/tickers')Ticker Not Found
When requesting a specific ticker that doesn't exist:
{
"error": "Ticker not found: INVALID_MINT_ADDRESS"
}Solutions:
- Verify the ticker_id format:
{BASE_MINT}_{QUOTE_MINT} - Ensure both mint addresses are valid Solana PublicKeys
- Check if the DAO is excluded via
EXCLUDED_DAOS - Verify the DAO has active pools with reserves
RPC Connection Issues
When the Solana RPC is unavailable:
{
"error": "Failed to fetch DAO data from blockchain"
}Solutions:
Verify your RPC provider is operational
Configure multiple RPC endpoints
Use a premium RPC provider
Implement automatic retry logic
Invalid Configuration
When required environment variables are missing:
{
"error": "FACTORY_ADDRESS not configured"
}Solution: Ensure all required environment variables are set in your .env file:
FACTORY_ADDRESS=YOUR_FACTORY_PROGRAM_ID
ROUTER_ADDRESS=YOUR_ROUTER_PROGRAM_IDError Handling Best Practices
Always Handle Errors
Never assume requests will succeed. Wrap all API calls in try-catch blocks.
try {
const data = await fetch('/api/tickers').then(r => r.json());
} catch (error) {
console.error('API request failed:', error);
// Handle error appropriately
}Implement Timeouts
Set reasonable timeouts to prevent hanging requests.
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000); // 10s timeout
try {
const response = await fetch('/api/tickers', {
signal: controller.signal
});
clearTimeout(timeout);
} catch (error) {
if (error.name === 'AbortError') {
console.error('Request timed out');
}
}Use Retry Logic
Implement exponential backoff for transient errors.
See code examples above for implementation details.
Cache Responses
Cache successful responses to reduce API load and improve resilience.
const cache = new Map();
const CACHE_TTL = 10000; // 10 seconds
async function getCached(url) {
const cached = cache.get(url);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const data = await fetch(url).then(r => r.json());
cache.set(url, { data, timestamp: Date.now() });
return data;
}Log Errors
Log all errors for debugging and monitoring.
async function fetchAPI(url) {
try {
return await fetch(url).then(r => r.json());
} catch (error) {
console.error({
timestamp: new Date().toISOString(),
url,
error: error.message,
stack: error.stack
});
throw error;
}
}Monitoring API Health
Use the health check endpoint to monitor API status:
curl https://your-api-domain.com/healthHealthy Response:
{
"status": "healthy",
"timestamp": "2024-01-01T00:00:00.000Z",
"uptime": 3600.5
}Set up automated health checks every 1-5 minutes to detect issues early.
Getting Support
If you encounter persistent errors:
Review API documentation for proper usage
Report bugs or request features
Get help from the community
Check configuration settings
Error Response Examples
{
"error": "Invalid ticker_id format. Expected: BASE_MINT_QUOTE_MINT"
}{
"error": "Endpoint not found: /api/invalid"
}{
"error": "Rate limit exceeded. Please try again later."
}{
"error": "Failed to fetch DAO data from blockchain"
}{
"error": "Service temporarily unavailable. Please try again in a few moments."
}Was this page helpful?