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.