Understanding V2 error codes, their meanings, and how to resolve them.
All V2 API errors return a consistent JSON structure:
{
"error": {
"type": "invalid_request_error",
"code": "missing_field",
"message": "The 'messages' field is required",
"param": "messages",
"request_id": "req-7f65ab21d1"
}
}| Field | Description |
|---|---|
| type | Category of error (authentication_error, rate_limit_error, server_error, etc.) |
| code | Specific error code for programmatic handling |
| message | Human-readable error description |
| param | The parameter that caused the error (if applicable) |
| request_id | Unique ID for support requests |
| Code | Type | Example Code | Description | Resolution |
|---|---|---|---|---|
| 400 | invalid_request_error | missing_field | Invalid request body or parameters | Check required fields (messages, model) |
| 401 | authentication_error | invalid_api_key | Missing or invalid API key | Check x-api-key header |
| 403 | forbidden_error | key_revoked | API key revoked or insufficient permissions | Generate new key in console |
| 404 | not_found_error | context_not_found | Resource not found or context expired | Verify context_id or model name |
| 409 | conflict_error | duplicate_id | Duplicate external_id in same context | Use unique IDs per message |
| 413 | invalid_request_error | payload_too_large | Request body exceeds size limit | Reduce message size or split batch |
| 422 | invalid_request_error | invalid_role | Invalid value for a field | Use valid roles: user, assistant, system |
| 429 | rate_limit_error | too_many_requests | Rate limit exceeded | Retry with exponential backoff |
| 500 | server_error | internal | Unexpected server error | Retry; contact support if persistent |
| 503 | server_error | service_unavailable | Service temporarily unavailable | Check status page, retry later |
x-api-key headerkaiko_live_xxx (production) or kaiko_test_xxx (staging)Retry-After header for wait timeX-RateLimit-Remaining headeremotion-v2stream: true for long responsesUse exponential backoff with jitter for transient errors (429, 500, 503):
async function callWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
// Retry on rate limit or server errors
if (error.status === 429 || error.status >= 500) {
const delay = Math.pow(2, i) * 1000 + Math.random() * 200;
console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
await new Promise(r => setTimeout(r, delay));
continue;
}
throw error; // Don't retry client errors (4xx except 429)
}
}
throw new Error('Max retries exceeded');
}x-api-key header/v2/...)request_id for support requestsrequest_id and timestampNext: see Rate Limits for quota details, or Changelog for recent updates.