Error Handling
CORTEX uses RFC 7807 Problem Details for all error responses, providing consistent, machine-readable error information.
Error Response Format
{
"type": "https://api.cortex.purplelab.ai/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Email is required",
"instance": "/auth/register"
}
Fields
| Field | Type | Description |
|---|---|---|
type | URI | A URI reference identifying the error type |
title | string | A short, human-readable summary |
status | number | The HTTP status code |
detail | string | A human-readable explanation |
instance | string | The request path that caused the error |
Additional Fields
Some errors include additional context:
{
"type": "https://api.cortex.purplelab.ai/errors/validation-error",
"title": "Validation Error",
"status": 400,
"detail": "Multiple validation errors occurred",
"instance": "/users",
"errors": [
{ "field": "email", "message": "must be a valid email" },
{ "field": "password", "message": "must be at least 8 characters" }
]
}
HTTP Status Codes
| Code | Meaning | Common Causes |
|---|---|---|
400 | Bad Request | Validation errors, malformed JSON |
401 | Unauthorized | Invalid/expired token, missing auth |
403 | Forbidden | Insufficient permissions |
404 | Not Found | Resource doesn't exist or access denied |
409 | Conflict | Duplicate resource, state conflict |
422 | Unprocessable | Business rule violation |
429 | Too Many Requests | Rate limit exceeded |
500 | Internal Error | Server-side error |
Handling Errors
TypeScript
interface ProblemDetails {
type: string;
title: string;
status: number;
detail: string;
instance: string;
errors?: { field: string; message: string }[];
}
async function apiCall<T>(url: string, options?: RequestInit): Promise<T> {
const response = await fetch(url, options);
if (!response.ok) {
const error: ProblemDetails = await response.json();
throw new ApiError(error);
}
return response.json();
}
class ApiError extends Error {
constructor(public details: ProblemDetails) {
super(details.detail);
this.name = 'ApiError';
}
get status(): number {
return this.details.status;
}
get type(): string {
return this.details.type;
}
}
React Error Handling
function ErrorDisplay({ error }: { error: ApiError }) {
return (
<div className="error-container">
<h3>{error.details.title}</h3>
<p>{error.details.detail}</p>
{error.details.errors && (
<ul>
{error.details.errors.map((e, i) => (
<li key={i}>
<strong>{e.field}:</strong> {e.message}
</li>
))}
</ul>
)}
</div>
);
}
Why RFC 7807?
- Standardized — Industry-standard format supported by many tools
- Machine-Readable — Easy to parse programmatically
- Extensible — Can include additional context
- Self-Documenting — Type URIs can link to documentation