This document provides a comprehensive reference for all error codes returned by the Girard AI API.
Response Format
All API responses follow a consistent format:
Success Response
{
"success": true,
"data": { ... },
"meta": {
"requestId": "req_abc123",
"page": 1,
"limit": 20,
"total": 100
}
}
Error Response
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": { ... },
"hint": "Suggestion for fixing the error"
},
"meta": {
"requestId": "req_abc123"
}
}
Authentication Errors (401)
These errors indicate problems with API authentication.
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
MISSING_API_KEY | 401 | No API key provided in request | Add Authorization: Bearer gai_sk_... header |
INVALID_API_KEY | 401 | API key format is invalid or key doesn't exist | Verify the API key is correct and active |
EXPIRED_API_KEY | 401 | API key has passed its expiration date | Generate a new API key in the dashboard |
REVOKED_API_KEY | 401 | API key has been manually revoked | Generate a new API key or contact admin |
Example
# Missing API key
curl https://api.girardai.com/v1/workflows
# Response
{
"success": false,
"error": {
"code": "MISSING_API_KEY",
"message": "API key is required",
"hint": "Add Authorization header with format: Bearer gai_sk_..."
}
}
Authorization Errors (403)
These errors indicate the API key is valid but lacks permission for the requested action.
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
INSUFFICIENT_PERMISSIONS | 403 | API key lacks required scope | Request a key with appropriate permissions |
ORGANIZATION_ACCESS_DENIED | 403 | API key cannot access this organization | Use a key associated with the correct org |
Example
{
"success": false,
"error": {
"code": "INSUFFICIENT_PERMISSIONS",
"message": "API key does not have permission to execute workflows",
"details": {
"required": ["workflow:execute"],
"granted": ["workflow:read"]
}
}
}
Resource Errors (404)
These errors indicate the requested resource doesn't exist.
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
RESOURCE_NOT_FOUND | 404 | Generic resource not found | Verify the resource ID is correct |
WORKFLOW_NOT_FOUND | 404 | Specified workflow doesn't exist | Check workflow ID or create the workflow |
RUN_NOT_FOUND | 404 | Specified workflow run doesn't exist | Verify the run ID |
CONNECTION_NOT_FOUND | 404 | Integration connection doesn't exist | Set up the connection first |
ORGANIZATION_NOT_FOUND | 404 | Organization doesn't exist | Verify organization ID |
Example
{
"success": false,
"error": {
"code": "WORKFLOW_NOT_FOUND",
"message": "Workflow not found",
"details": {
"workflowId": "wf_abc123"
}
}
}
Validation Errors (400/422)
These errors indicate problems with the request data.
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
BAD_REQUEST | 400 | Generic bad request | Review request format |
VALIDATION_ERROR | 422 | Request body failed validation | Check details for specific field errors |
INVALID_REQUEST_BODY | 400 | Request body is malformed | Ensure valid JSON format |
MISSING_REQUIRED_FIELD | 400 | Required field is missing | Add the missing field |
INVALID_FIELD_VALUE | 400 | Field value is invalid | Check field constraints |
WORKFLOW_INACTIVE | 400 | Attempted to execute inactive workflow | Activate the workflow first |
FILE_TOO_LARGE | 400 | Uploaded file exceeds size limit | Reduce file size (max 10MB) |
INVALID_FILE_TYPE | 400 | File type not supported | Use a supported file format |
NO_FILE_PROVIDED | 400 | File upload expected but not received | Include file in request |
Validation Error Example
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation failed",
"details": [
{
"path": "steps[0].config.prompt",
"message": "Required field is missing"
},
{
"path": "name",
"message": "String must contain at least 1 character(s)"
}
]
}
}
Rate Limiting Errors (429)
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Too many requests | Wait and retry after the specified time |
RATE_LIMITED | 429 | Generic rate limit | Check Retry-After header |
Rate Limit Headers
When rate limited, check these response headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed per window |
X-RateLimit-Remaining | Requests remaining in current window |
X-RateLimit-Reset | Unix timestamp when the window resets |
Retry-After | Seconds to wait before retrying |
Example
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Please try again later.",
"details": {
"limit": 100,
"remaining": 0,
"resetAt": "2026-01-22T12:00:00Z",
"retryAfter": 45
}
}
}
Server Errors (5xx)
These errors indicate server-side issues.
| Code | HTTP Status | Description | Resolution |
|---|---|---|---|
INTERNAL_ERROR | 500 | Unexpected server error | Retry request; contact support if persistent |
DATABASE_ERROR | 500 | Database operation failed | Retry request; check status page |
AI_PROVIDER_ERROR | 500 | AI provider returned an error | Retry; may be temporary provider issue |
EXTERNAL_SERVICE_ERROR | 502 | External service failed | Check integration status |
SERVICE_UNAVAILABLE | 503 | Service temporarily down | Wait and retry; check status page |
STORAGE_NOT_CONFIGURED | 503 | File storage not set up | Contact support |
AI_NOT_CONFIGURED | 503 | AI provider not configured | Check API key configuration |
TIMEOUT | 504 | Request timed out | Retry with smaller payload or simpler request |
Example
{
"success": false,
"error": {
"code": "AI_PROVIDER_ERROR",
"message": "AI provider returned an error",
"details": {
"provider": "anthropic",
"originalError": "Rate limit exceeded"
}
}
}
Error Handling Best Practices
1. Always Check success Field
const response = await fetch('/api/v1/workflows', {
headers: { Authorization: `Bearer ${apiKey}` }
});
const data = await response.json();
if (!data.success) {
console.error(`Error ${data.error.code}: ${data.error.message}`);
// Handle error based on code
return;
}
// Use data.data safely
console.log(data.data);
2. Implement Retry Logic for Transient Errors
async function fetchWithRetry(url: string, options: RequestInit, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
const data = await response.json();
if (data.success) return data;
// Retry on transient errors
const retryableCodes = ['RATE_LIMITED', 'SERVICE_UNAVAILABLE', 'TIMEOUT'];
if (retryableCodes.includes(data.error.code)) {
const retryAfter = data.error.details?.retryAfter || Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
// Don't retry on permanent errors
throw new Error(data.error.message);
}
throw new Error('Max retries exceeded');
}
3. Handle Specific Error Codes
switch (data.error.code) {
case 'MISSING_API_KEY':
case 'INVALID_API_KEY':
// Redirect to API key setup
break;
case 'RATE_LIMIT_EXCEEDED':
// Show rate limit message, implement backoff
break;
case 'VALIDATION_ERROR':
// Show field-level errors to user
const fieldErrors = data.error.details;
break;
case 'WORKFLOW_NOT_FOUND':
// Resource doesn't exist
break;
default:
// Generic error handling
break;
}
4. Log Request IDs for Support
Always log the requestId from the meta field when encountering errors:
if (!data.success) {
console.error(`Error ${data.error.code} (Request ID: ${data.meta?.requestId})`);
// Include requestId when contacting support
}
SDK Error Handling
Node.js SDK
import { Girard AI, GirardAIError } from '@girardai/sdk';
const client = new Girard AI({ apiKey: 'gai_sk_...' });
try {
const workflow = await client.workflows.execute('wf_123', { input: {} });
} catch (error) {
if (error instanceof GirardAIError) {
console.log('Code:', error.code);
console.log('Message:', error.message);
console.log('Request ID:', error.requestId);
if (error.code === 'RATE_LIMIT_EXCEEDED') {
// Handle rate limiting
}
}
}
Python SDK
from girardai import Girard AI, GirardAIError
client = Girard AI(api_key="gai_sk_...")
try:
workflow = client.workflows.execute("wf_123", input={})
except GirardAIError as e:
print(f"Code: {e.code}")
print(f"Message: {e.message}")
print(f"Request ID: {e.request_id}")
if e.code == "RATE_LIMIT_EXCEEDED":
# Handle rate limiting
pass
Status Codes Summary
| HTTP Status | Meaning | Common Codes |
|---|---|---|
| 200 | Success | - |
| 400 | Bad Request | BAD_REQUEST, INVALID_REQUEST_BODY |
| 401 | Unauthorized | MISSING_API_KEY, INVALID_API_KEY |
| 403 | Forbidden | INSUFFICIENT_PERMISSIONS |
| 404 | Not Found | *_NOT_FOUND |
| 409 | Conflict | CONFLICT |
| 422 | Validation Error | VALIDATION_ERROR |
| 429 | Rate Limited | RATE_LIMIT_EXCEEDED |
| 500 | Server Error | INTERNAL_ERROR, DATABASE_ERROR |
| 502 | Bad Gateway | EXTERNAL_SERVICE_ERROR |
| 503 | Service Unavailable | SERVICE_UNAVAILABLE |
| 504 | Timeout | TIMEOUT |
Support
If you encounter persistent errors:
- Check the Status Page for known issues
- Include the
requestIdwhen contacting support - Email: api-support@girardai.com
- Documentation: API Reference