Error envelope
Every error response includes at least two fields: a human-readable error message and a stable machine-readable code. Some errors include additional context fields.
Error response structure
{
"error": "Human-readable description of what went wrong",
"code": "MACHINE_READABLE_CODE",
"details": { } // optional, present on validation errors
}Tip
code field for programmatic branching. The error message may change between releases to improve clarity.HTTP status codes
| Status | Meaning | Typical cause |
|---|---|---|
400 | Bad Request | Malformed JSON, missing required fields, or invalid parameter values |
401 | Unauthorized | Missing or invalid API key |
403 | Forbidden | Valid key but insufficient scopes for this operation |
404 | Not Found | Resource does not exist or is not accessible to this key |
409 | Conflict | Idempotency key reuse with a different payload |
422 | Unprocessable Entity | Syntactically valid request but semantically invalid data |
429 | Too Many Requests | Rate limit exceeded for this key and route |
500 | Internal Server Error | Unexpected server-side failure |
503 | Service Unavailable | Temporary outage or maintenance window |
Error codes
Machine-readable codes are stable identifiers you can match in your error handling logic. Common codes:
| Code | Status | Description |
|---|---|---|
UNAUTHORIZED | 401 | API key is missing or invalid |
FORBIDDEN | 403 | Key lacks required scopes |
NOT_FOUND | 404 | Resource does not exist |
VALIDATION_ERROR | 400/422 | Request body failed schema validation |
IDEMPOTENCY_KEY_REUSED | 409 | Idempotency key reused with a different payload |
IDEMPOTENCY_IN_PROGRESS | 409 | Another request with the same idempotency key is still running |
CONFLICT | 409 | General conflict response for duplicate or incompatible state changes |
RATE_LIMITED | 429 | Rate limit exceeded |
INTERNAL_ERROR | 500 | Unexpected server failure |
Validation errors
When the request body fails validation, the response includes a details object with per-field errors to help pinpoint the issue.
Validation error example
{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"details": {
"title": "Required field is missing",
"status": "Must be one of: open, in_progress, addressed"
}
}Retry classification
Not all errors are retryable. Use this classification to decide whether to retry a failed request:
| Category | Statuses | Action |
|---|---|---|
Retryable | 429, 500, 503 | Retry with exponential backoff |
Client error | 400, 401, 403, 404, 409, 422 | Fix the request before retrying |
Idempotent safe | Any (with key) | POST/PATCH and supported DELETE routes can be retried safely with Idempotency-Key |
Note
Handling errors in code
TypeScript error handling
try {
const issue = await client.issues.create({
title: "Safety observation",
status: "open"
});
} catch (err) {
switch (err.code) {
case "VALIDATION_ERROR":
console.error("Fix request:", err.details);
break;
case "RATE_LIMITED":
// SDK retries automatically; this fires after max retries exhausted
console.warn("Rate limited, try again later");
break;
case "UNAUTHORIZED":
console.error("Check API key configuration");
break;
default:
console.error("Unexpected error:", err.error);
}
}