Skip to main content

Error Handling

Standard error responses and error codes.

Error Response Format

All errors follow this format:

{
"status": "error",
"message": "Human-readable error description",
"error": {
"code": "ERROR_CODE",
"details": ["Additional details if available"]
}
}

HTTP Status Codes

400 Bad Request

Validation or client errors.

{
"status": "error",
"message": "Validation failed: question is required",
"error": {
"code": "VALIDATION_ERROR",
"details": [
"question: is required",
"conversationId: must be a valid ObjectId"
]
}
}

401 Unauthorized

Authentication required or token invalid.

{
"status": "error",
"message": "Authentication required",
"error": {
"code": "AUTH_REQUIRED"
}
}
{
"status": "error",
"message": "Token expired",
"error": {
"code": "TOKEN_EXPIRED"
}
}

403 Forbidden

Authenticated but lacks permission.

{
"status": "error",
"message": "Access denied to this workspace",
"error": {
"code": "ACCESS_DENIED"
}
}
{
"status": "error",
"message": "Permission denied: canInvite",
"error": {
"code": "PERMISSION_DENIED",
"details": ["Required permission: canInvite"]
}
}

404 Not Found

Resource doesn't exist.

{
"status": "error",
"message": "Conversation not found",
"error": {
"code": "NOT_FOUND"
}
}

409 Conflict

Resource conflict (duplicate, etc.).

{
"status": "error",
"message": "User already exists with this email",
"error": {
"code": "DUPLICATE_RESOURCE"
}
}

429 Too Many Requests

Rate limit exceeded.

{
"status": "error",
"message": "Too many requests, please try again later",
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"details": ["Retry after 60 seconds"]
}
}

Headers included:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1704067260
Retry-After: 60

500 Internal Server Error

Server-side error.

{
"status": "error",
"message": "An unexpected error occurred",
"error": {
"code": "INTERNAL_ERROR"
}
}

In development, includes stack trace:

{
"status": "error",
"message": "Cannot read property 'id' of undefined",
"error": {
"code": "INTERNAL_ERROR"
},
"stack": "TypeError: Cannot read property...\n at processQuery..."
}

503 Service Unavailable

Dependency unavailable.

{
"status": "error",
"message": "LLM service unavailable",
"error": {
"code": "SERVICE_UNAVAILABLE",
"details": ["Azure OpenAI connection failed"]
}
}

Error Codes Reference

Authentication Errors

CodeDescription
AUTH_REQUIREDNo authentication provided
TOKEN_EXPIREDJWT token has expired
TOKEN_INVALIDJWT token is malformed
REFRESH_TOKEN_INVALIDRefresh token invalid or expired
INVALID_CREDENTIALSWrong email or password

Authorization Errors

CodeDescription
ACCESS_DENIEDNo access to resource
PERMISSION_DENIEDMissing required permission
OWNER_REQUIREDOperation requires owner role

Validation Errors

CodeDescription
VALIDATION_ERRORRequest body validation failed
INVALID_IDInvalid ObjectId format
MISSING_REQUIRED_FIELDRequired field not provided
INVALID_FIELD_VALUEField value invalid

Resource Errors

CodeDescription
NOT_FOUNDResource doesn't exist
DUPLICATE_RESOURCEResource already exists
RESOURCE_EXPIREDResource has expired

RAG Errors

CodeDescription
RAG_NO_CONTEXTNo relevant documents found
RAG_LLM_ERRORLLM generation failed
RAG_TIMEOUTRequest timed out
RAG_LOW_CONFIDENCEAnswer confidence too low

Sync Errors

CodeDescription
SYNC_IN_PROGRESSSync already running
SYNC_FAILEDSync job failed

System Errors

CodeDescription
INTERNAL_ERRORUnexpected server error
SERVICE_UNAVAILABLEExternal service down
RATE_LIMIT_EXCEEDEDToo many requests
MAINTENANCE_MODESystem under maintenance

Client Error Handling

JavaScript Example

async function apiCall(endpoint, options) {
try {
const response = await fetch(endpoint, options);
const data = await response.json();

if (!response.ok) {
switch (response.status) {
case 401:
if (data.error?.code === 'TOKEN_EXPIRED') {
await refreshToken();
return apiCall(endpoint, options); // Retry
}
redirectToLogin();
break;

case 403:
showError('You do not have permission for this action');
break;

case 429:
const retryAfter = response.headers.get('Retry-After');
showError(`Rate limited. Try again in ${retryAfter}s`);
break;

default:
showError(data.message || 'An error occurred');
}
throw new ApiError(data);
}

return data;
} catch (error) {
if (error instanceof ApiError) throw error;
throw new NetworkError('Network request failed');
}
}

React Hook Example

function useApiError() {
const handleError = useCallback((error: ApiError) => {
switch (error.code) {
case 'AUTH_REQUIRED':
case 'TOKEN_EXPIRED':
logout();
navigate('/login');
break;

case 'PERMISSION_DENIED':
toast.error('Permission denied');
break;

case 'RATE_LIMIT_EXCEEDED':
toast.warning('Too many requests. Please slow down.');
break;

default:
toast.error(error.message);
}
}, []);

return { handleError };
}