Skip to main content
ChainGuard API uses standard HTTP status codes and provides detailed error information.

Error Response Format

All errors follow a consistent structure:
interface ErrorResponse {
  success: false;
  error: {
    code: string;           // Machine-readable error code
    message: string;        // Human-readable description
    details?: object;       // Additional context
    field?: string;         // For validation errors
  };
  meta: {
    requestId: string;
    timestamp: string;
  };
}

Example Error Response

{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid Ethereum address format",
    "field": "address",
    "details": {
      "provided": "0xinvalid",
      "expected": "42 character hex string starting with 0x"
    }
  },
  "meta": {
    "requestId": "req_abc123def456",
    "timestamp": "2024-01-15T14:32:00.847Z"
  }
}

HTTP Status Codes

  • 200: Success. Retry: Not needed.
  • 201: Created. Retry: Not needed.
  • 400: Bad request. Retry: No.
  • 401: Unauthorized. Retry: No.
  • 403: Forbidden. Retry: No.
  • 404: Not found. Retry: No.
  • 429: Rate limited. Retry: Yes, with backoff.
  • 500: Server error. Retry: Yes, with backoff.
  • 502: Bad gateway. Retry: Yes, with backoff.
  • 503: Service unavailable. Retry: Yes, with backoff.

Error Codes Reference

Authentication Errors

  • MISSING_AUTH (401): Authorization header not provided.
  • INVALID_API_KEY (401): API key format is invalid.
  • EXPIRED_API_KEY (401): API key has been revoked.
  • INSUFFICIENT_SCOPE (403): Key lacks required permissions.

Validation Errors

  • VALIDATION_ERROR (400): Request body validation failed.
  • INVALID_ADDRESS (400): Blockchain address format invalid.
  • INVALID_CHAIN (400): Unsupported blockchain.
  • INVALID_URL (400): URL format invalid.
  • MISSING_PARAMETER (400): Required parameter not provided.

Resource Errors

  • NOT_FOUND (404): Requested resource does not exist.
  • CONTRACT_NOT_FOUND (404): Contract not deployed at address.
  • CHAIN_NOT_SUPPORTED (400): Chain ID not supported.

Rate Limiting

  • RATE_LIMIT_EXCEEDED (429): Too many requests.
  • QUOTA_EXCEEDED (429): Daily quota reached.

Server Errors

  • INTERNAL_ERROR (500): Unexpected server error.
  • SERVICE_UNAVAILABLE (503): Service temporarily down.
  • UPSTREAM_ERROR (502): Data provider unavailable.

Retry Strategy

Implement exponential backoff for transient errors:
async function fetchWithRetry(
  url: string, 
  options: RequestInit, 
  maxRetries = 3
): Promise<Response> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);
      
      // Don't retry client errors (except 429)
      if (response.status >= 400 && response.status < 500 && response.status !== 429) {
        return response;
      }
      
      // Handle rate limiting
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After');
        const waitMs = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000;
        await sleep(waitMs);
        continue;
      }
      
      // Retry server errors
      if (response.status >= 500) {
        const waitMs = Math.pow(2, attempt) * 1000;  // 1s, 2s, 4s
        await sleep(waitMs);
        continue;
      }
      
      return response;
      
    } catch (error) {
      // Network error - retry with backoff
      if (attempt === maxRetries - 1) throw error;
      await sleep(Math.pow(2, attempt) * 1000);
    }
  }
  
  throw new Error('Max retries exceeded');
}

function sleep(ms: number): Promise<void> {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Rate Limit Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705329720
Retry-After: 30

Error Handling Examples

JavaScript/TypeScript

import { ChainGuard, APIError } from '@chainguard/sdk';

const client = new ChainGuard({ apiKey });

try {
  const result = await client.scan.url('https://example.com');
} catch (error) {
  if (error instanceof APIError) {
    switch (error.code) {
      case 'RATE_LIMIT_EXCEEDED':
        // Wait and retry
        await sleep(error.retryAfter * 1000);
        break;
      case 'INVALID_API_KEY':
        // Check API key configuration
        console.error('Invalid API key');
        break;
      case 'VALIDATION_ERROR':
        // Fix request parameters
        console.error('Validation error:', error.field, error.message);
        break;
      default:
        console.error('API error:', error.message);
    }
  } else {
    // Network or other error
    console.error('Request failed:', error);
  }
}

Python

from chainguard import ChainGuard, APIError, RateLimitError
import time

client = ChainGuard(api_key=api_key)

try:
    result = client.scan.url('https://example.com')
except RateLimitError as e:
    time.sleep(e.retry_after)
    result = client.scan.url('https://example.com')
except APIError as e:
    print(f"API Error: {e.code} - {e.message}")
except Exception as e:
    print(f"Request failed: {e}")

Debugging

Include your request ID when contacting support:
{
  "meta": {
    "requestId": "req_abc123def456"  // Include this in support tickets
  }
}
Request IDs are unique per request and help our team trace issues through our systems.