Error Handling
Learn how to properly handle errors from the CID222 API to build resilient applications.
Error Response Format
All API errors follow a consistent format:
Error Response
{"statusCode": 400,"message": "Detailed error message","error": "Bad Request","details": {// Additional context when available}}
HTTP Status Codes
| Code | Description | Action |
|---|---|---|
400 | Bad Request | Fix request body/parameters |
401 | Unauthorized | Check API key |
403 | Forbidden | Content blocked or insufficient permissions |
404 | Not Found | Check endpoint URL or resource ID |
429 | Rate Limited | Retry after delay |
500 | Internal Error | Retry with backoff |
503 | Service Unavailable | Provider down, retry later |
Common Errors
Authentication Errors
401 - Invalid Token
{"statusCode": 401,"message": "Invalid or expired token","error": "Unauthorized"}
Solutions:
- Verify API key is correct
- Check if key has been rotated
- Ensure Bearer prefix is included
Content Blocked
403 - Content Blocked
{"statusCode": 403,"message": "Request blocked due to policy violation","error": "Forbidden","details": {"reason": "TOXIC_CONTENT","category": "HATE_SPEECH","confidence": 0.94}}
When content is blocked, the request was not forwarded to the LLM. No tokens were consumed.
Rate Limiting
429 - Rate Limit
{"statusCode": 429,"message": "Rate limit exceeded","error": "Too Many Requests","details": {"retry_after": 30,"limit": 60,"remaining": 0,"reset": 1699900030}}
Handle rate limits by waiting before retrying:
Rate Limit Handler
async function handleRateLimit(response) {const retryAfter = response.headers.get('Retry-After');const waitTime = retryAfter ? parseInt(retryAfter) * 1000 : 30000;console.log(`Rate limited. Waiting ${waitTime}ms...`);await new Promise(resolve => setTimeout(resolve, waitTime));// Retry the request}
Stream Error Handling
SSE streams may encounter errors mid-stream:
Stream Error Handling
async function handleStream(response) {const reader = response.body.getReader();const decoder = new TextDecoder();try {while (true) {const { done, value } = await reader.read();if (done) break;const chunk = decoder.decode(value);// Check for error eventif (chunk.includes('event: error')) {const errorData = parseStreamError(chunk);throw new Error(errorData.message);}// Process normal dataprocessChunk(chunk);}} catch (error) {console.error('Stream error:', error);// Handle gracefully - maybe show partial response} finally {reader.releaseLock();}}function parseStreamError(chunk) {const match = chunk.match(/data: ({.*})/);if (match) {return JSON.parse(match[1]);}return { message: 'Unknown stream error' };}
Retry Strategies
Different errors require different retry approaches:
| Error Type | Should Retry | Strategy |
|---|---|---|
| 400 Bad Request | No | Fix input and resubmit |
| 401 Unauthorized | Once | Refresh token, then retry |
| 403 Forbidden | No | Content violation, don't retry |
| 429 Rate Limited | Yes | Wait for Retry-After header |
| 500 Server Error | Yes | Exponential backoff |
| 503 Unavailable | Yes | Exponential backoff |
Complete Error Handler
class CID222Client {async request(endpoint, body, retries = 3) {for (let attempt = 0; attempt < retries; attempt++) {try {const response = await fetch(`https://api.cid222.ai${endpoint}`, {method: 'POST',headers: {'Authorization': `Bearer ${this.apiKey}`,'Content-Type': 'application/json',},body: JSON.stringify(body)});if (response.ok) {return response.json();}const error = await response.json();// Don't retry client errorsif (response.status >= 400 && response.status < 500) {if (response.status === 429) {const retryAfter = response.headers.get('Retry-After') || '30';await this.sleep(parseInt(retryAfter) * 1000);continue;}throw new APIError(error.message, response.status);}// Retry server errors with backoffif (attempt < retries - 1) {await this.sleep(Math.pow(2, attempt) * 1000);continue;}throw new APIError(error.message, response.status);} catch (error) {if (attempt === retries - 1) throw error;}}}sleep(ms) {return new Promise(resolve => setTimeout(resolve, ms));}}class APIError extends Error {constructor(message, status) {super(message);this.status = status;}}