Skip to main content

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​

CodeDescriptionCommon Causes
200Success-
201CreatedResource created successfully
400Bad RequestInvalid request body or parameters
401UnauthorizedMissing or invalid API key
403ForbiddenInvalid API key
404Not FoundResource not found
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer 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.