Error Handling
Learn how ConstellationAPI handles errors and how to handle them in your application.
Error Response Format
All errors follow a consistent format:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message"
}
}
HTTP Status Codes
| Code | Description | Common Causes |
|---|---|---|
| 200 | Success | - |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request body or parameters |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Invalid API key |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
Common Error Codes
Authentication Errors
UNAUTHORIZED
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid API key"
}
}
FORBIDDEN
{
"success": false,
"error": {
"code": "FORBIDDEN",
"message": "Invalid API key"
}
}
Tenant Errors
TENANT_NOT_FOUND
{
"success": false,
"error": {
"code": "TENANT_NOT_FOUND",
"message": "Tenant 'my-tenant' not found"
}
}
Validation Errors
VALIDATION_ERROR
{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid tenant ID format"
}
}
Integration Errors
INTEGRATION_NOT_AUTHORIZED
{
"success": false,
"error": {
"code": "INTEGRATION_NOT_AUTHORIZED",
"message": "JIRA integration not authorized for this tenant"
}
}
Handling Errors
JavaScript/Node.js
try {
const response = await fetch('http://localhost:3007/jira/projects', {
headers: {
'X-API-KEY': 'your-internal-key',
'X-Tenant-Id': 'my-tenant',
},
});
const data = await response.json();
if (!response.ok) {
if (data.error) {
switch (data.error.code) {
case 'UNAUTHORIZED':
// Handle authentication error
break;
case 'TENANT_NOT_FOUND':
// Handle tenant error
break;
default:
// Handle other errors
}
}
throw new Error(data.error.message);
}
return data;
} catch (error) {
console.error('API Error:', error);
throw error;
}
Python
import requests
try:
response = requests.get(
'http://localhost:3007/jira/projects',
headers={
'X-API-KEY': 'your-internal-key',
'X-Tenant-Id': 'my-tenant',
}
)
response.raise_for_status()
data = response.json()
return data
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401:
# Handle authentication error
pass
elif e.response.status_code == 404:
# Handle not found
pass
raise
Retry Logic
For transient errors (5xx), implement retry logic:
async function fetchWithRetry(url, options, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.ok) {
return await response.json();
}
if (response.status < 500) {
// Don't retry client errors
throw new Error(`Client error: ${response.status}`);
}
} catch (error) {
if (i === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
Rate Limiting
When rate limited (429), check response headers:
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Wait until X-RateLimit-Reset before retrying.