Версия: 1.1 Дата обновления: 17 ноября 2025
Accellens API использует стандартизированный формат обработки ошибок для обеспечения консистентности и удобства отладки. Все ошибки возвращаются в едином формате с кодами ошибок, сообщениями и дополнительными деталями.
API Gateway возвращает ошибки в следующем формате:
{
"error": "Error type",
"message": "Human-readable error message",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}Для ошибок с кодом (409, 429):
{
"error": "Error message",
"code": "ERROR_CODE",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}Python сервисы возвращают ошибки в стандартном формате FastAPI:
{
"detail": "Human-readable error message"
}Для валидационных ошибок (422):
{
"detail": [
{
"type": "string_type",
"loc": ["body", "field_name"],
"msg": "Error message",
"input": "invalid_value"
}
]
}| HTTP Status | Описание | Примеры |
|---|---|---|
400 Bad Request |
Некорректный запрос | Невалидные параметры, отсутствующие обязательные поля |
401 Unauthorized |
Не авторизован | Отсутствует или невалидный токен |
403 Forbidden |
Доступ запрещён | Недостаточно прав для операции |
404 Not Found |
Ресурс не найден | Проект, сканирование или endpoint не существует |
409 Conflict |
Конфликт | Дублирование ресурса, конфликтующее состояние |
422 Unprocessable Entity |
Необрабатываемая сущность | Валидационные ошибки |
429 Too Many Requests |
Превышен лимит запросов | Rate limit exceeded |
500 Internal Server Error |
Внутренняя ошибка сервера | Неожиданная ошибка |
502 Bad Gateway |
Ошибка шлюза | Проблема с upstream сервисом |
503 Service Unavailable |
Сервис недоступен | Временная недоступность сервиса |
504 Gateway Timeout |
Таймаут шлюза | Timeout при обращении к upstream |
Gateway использует следующие коды ошибок в поле code:
| Код | HTTP Status | Описание |
|---|---|---|
NOT_FOUND |
404 | Ресурс не найден |
VALIDATION_ERROR |
400 | Ошибка валидации |
UNAUTHORIZED |
401 | Не авторизован |
FORBIDDEN |
403 | Доступ запрещён |
CONFLICT |
409 | Конфликт |
RATE_LIMIT_EXCEEDED |
429 | Превышен лимит запросов |
INTERNAL_SERVER_ERROR |
500 | Внутренняя ошибка |
UNKNOWN_ERROR |
500 | Неизвестная ошибка |
Python сервисы возвращают детальные сообщения в поле detail. Ниже приведены примеры реальных сообщений:
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 400 | Invalid UUID provided | Некорректный UUID |
| 403 | Users can only access their own settings | Доступ к чужим настройкам |
| 401 | Invalid credentials | Неверные учётные данные |
| 403 | User account is inactive | Неактивный аккаунт |
| 403 | User account is locked | Заблокированный аккаунт |
| 401 | Password not set for this user | Пароль не установлен |
| 409 | User with this email already exists | Дублирование email |
| 404 | User not found | Пользователь не найден |
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 403 | Organization mismatch between actor and payload | Несоответствие организации |
| 409 | Project with slug '{slug}' already exists in this organization | Дублирование slug |
| 400 | Invalid ID format | Некорректный формат ID |
| 404 | Project not found | Проект не найден |
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 400 | {section}.{field} is required for {type} integration | Отсутствует обязательное поле |
| 400 | credentials are required for {type} integration | Отсутствуют credentials |
| 400 | settings are required for {type} integration | Отсутствуют settings |
| 400 | Invalid organization ID | Некорректный ID организации |
| 403 | Organization mismatch between path and access context | Несоответствие организации |
| 409 | Integration type already configured for this organization | Дублирование типа интеграции |
| 400 | Invalid integration ID | Некорректный ID интеграции |
| 404 | Integration not found | Интеграция не найдена |
| 400 | Invalid integration type: {type} | Некорректный тип интеграции |
| 403 | Organization mismatch | Несоответствие организации |
| 400 | OAuth not supported for integration type: {type} | OAuth не поддерживается |
| 400 | Invalid or expired OAuth state | Невалидный OAuth state |
| 404 | OAuth state not found | OAuth state не найден |
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 400 | Webhook URL exceeds maximum length of {N} characters | URL слишком длинный |
| 400 | Webhook URL must include a scheme (http:// or https://) | Отсутствует схема |
| 400 | Webhook URL must use http:// or https:// scheme | Некорректная схема |
| 400 | Webhook URL must use HTTPS in production environment | HTTP в production |
| 400 | Webhook URL must include a valid hostname | Некорректный hostname |
| 400 | Webhook URL cannot point to private, loopback, or link-local addresses | Приватный адрес |
| 400 | Invalid ID format | Некорректный формат ID |
| 404 | Webhook not found | Webhook не найден |
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 400 | Invalid ID format | Некорректный формат ID |
| 404 | Run not found | Run не найден |
| 403 | Actor does not have access to this project | Нет доступа к проекту |
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 400 | Invalid ID format | Некорректный формат ID |
| 404 | API key not found | API ключ не найден |
| 400 | Cannot rotate inactive API key | Нельзя ротировать неактивный ключ |
| HTTP Status | Сообщение | Контекст |
|---|---|---|
| 400 | Invalid run ID format: {run_id} | Некорректный формат ID run |
| 404 | Run not found: {run_id} | Run не найден |
| 403 | Run does not belong to this organization | Run не принадлежит организации |
| 403 | Actor does not have access to this project | Нет доступа к проекту |
| 404 | Project not found for run: {run_id} | Проект не найден |
| 501 | PDF report generation is not yet implemented | PDF экспорт не реализован |
| 500 | Failed to generate PDF report: {error} | Ошибка генерации PDF |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
AUTH_REQUIRED |
401 | Требуется аутентификация | Передайте валидный токен в заголовке Authorization |
AUTH_INVALID_TOKEN |
401 | Невалидный токен | Проверьте токен или обновите его |
AUTH_TOKEN_EXPIRED |
401 | Токен истёк | Access token истёк. Используйте /api/v1/auth/refresh для получения нового access token. Refresh token передаётся автоматически через httpOnly cookie. |
AUTH_INSUFFICIENT_PERMISSIONS |
403 | Недостаточно прав | Обратитесь к администратору для получения прав |
AUTH_API_KEY_INVALID |
401 | Невалидный API ключ | Проверьте API ключ в заголовке X-Accellens-Key |
AUTH_API_KEY_REVOKED |
401 | API ключ отозван | Создайте новый API ключ |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
PROJECT_NOT_FOUND |
404 | Проект не найден | Проверьте slug проекта |
PROJECT_ALREADY_EXISTS |
409 | Проект с таким slug уже существует | Используйте другой slug |
PROJECT_SLUG_INVALID |
422 | Некорректный slug проекта | Slug должен соответствовать формату: [a-z0-9-]+ |
PROJECT_ACCESS_DENIED |
403 | Доступ к проекту запрещён | Проверьте права доступа к проекту |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
SCAN_NOT_FOUND |
404 | Сканирование не найдено | Проверьте идентификатор сканирования |
SCAN_LIMIT_REACHED |
429 | Превышен лимит параллельных сканирований | Дождитесь завершения текущих сканирований |
SCAN_INVALID_URL |
422 | Некорректный URL | URL должен быть валидным HTTP/HTTPS URL |
SCAN_TIMEOUT |
504 | Таймаут сканирования | Увеличьте timeout или проверьте доступность URL |
SCAN_ALREADY_RUNNING |
409 | Сканирование уже выполняется | Дождитесь завершения текущего сканирования |
SCAN_CANCELLED |
409 | Сканирование отменено | Запустите новое сканирование |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
VALIDATION_ERROR |
422 | Ошибка валидации | Проверьте формат данных запроса |
VALIDATION_FIELD_REQUIRED |
422 | Обязательное поле отсутствует | Укажите все обязательные поля |
VALIDATION_FIELD_INVALID |
422 | Некорректное значение поля | Проверьте формат и допустимые значения |
VALIDATION_FIELD_TOO_LONG |
422 | Поле превышает максимальную длину | Уменьшите длину поля |
VALIDATION_FIELD_TOO_SHORT |
422 | Поле меньше минимальной длины | Увеличьте длину поля |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
UNSUPPORTED_FORMAT |
422 | Неподдерживаемый формат | Используйте один из поддерживаемых форматов: json, pdf, sarif (в MVP/v1). allure планируется для v2+ |
EXPORT_FAILED |
500 | Ошибка экспорта | Повторите запрос позже |
EXPORT_NOT_READY |
202 | Экспорт ещё не готов | Дождитесь завершения экспорта |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
ASSISTIVE_DISABLED |
422 | Ассистивная симуляция отключена | Включите симуляцию в настройках проекта |
ASSISTIVE_NOT_SUPPORTED |
422 | Ассистивная технология не поддерживается | Используйте поддерживаемую технологию |
ASSISTIVE_SIMULATION_FAILED |
500 | Ошибка симуляции | Повторите запрос позже |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
RATE_LIMIT_EXCEEDED |
429 | Превышен лимит запросов | Дождитесь сброса лимита (см. заголовок Retry-After) |
RATE_LIMIT_QUOTA_EXCEEDED |
429 | Превышена квота запросов | Обновите план подписки |
| Код | HTTP Status | Описание | Решение |
|---|---|---|---|
INTERNAL_ERROR |
500 | Внутренняя ошибка сервера | Повторите запрос позже или обратитесь в поддержку |
SERVICE_UNAVAILABLE |
503 | Сервис временно недоступен | Повторите запрос позже |
UPSTREAM_ERROR |
502 | Ошибка upstream сервиса | Повторите запрос позже |
DATABASE_ERROR |
500 | Ошибка базы данных | Повторите запрос позже или обратитесь в поддержку |
{
"detail": [
{
"type": "string_type",
"loc": ["body", "name"],
"msg": "Input should be a valid string",
"input": null
},
{
"type": "string_type",
"loc": ["body", "slug"],
"msg": "String should match pattern '^[a-z0-9-]+$'",
"input": "Invalid Slug!"
}
]
}HTTP Status: 422 Unprocessable Entity
{
"error": "Bad Request",
"message": "Validation failed: slug must match pattern [a-z0-9-]+",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}HTTP Status: 400 Bad Request
{
"error": "Not found",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}HTTP Status: 404 Not Found
{
"detail": "Project not found"
}HTTP Status: 404 Not Found
{
"error": "Rate limit exceeded",
"code": "RATE_LIMIT_EXCEEDED",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}HTTP Status: 429 Too Many Requests
Заголовки:
X-RateLimit-Limit: 200X-RateLimit-Remaining: 0X-RateLimit-Reset: 1699603200Retry-After: 60
{
"detail": "Rate limit exceeded. Maximum 200 requests per minute"
}HTTP Status: 429 Too Many Requests
{
"error": "Internal Server Error",
"message": "An unexpected error occurred",
"requestId": "550e8400-e29b-41d4-a716-446655440000"
}HTTP Status: 500 Internal Server Error
{
"detail": "Internal server error"
}HTTP Status: 500 Internal Server Error
Все ответы об ошибках от Gateway содержат requestId для трейсинга запроса в логах системы.
Клиенты могут передавать собственный X-Request-Id для корреляции запросов:
X-Request-Id: my-custom-request-id-123Gateway вернёт этот же ID в ответе:
{
"error": "Not found",
"requestId": "my-custom-request-id-123"
}Python сервисы используют OpenTelemetry для трейсинга. Request ID передаётся через заголовки и логируется в структурированных логах.
interface GatewayError {
error: string;
message?: string;
code?: string;
requestId: string;
}
async function handleGatewayError(response: Response): Promise<never> {
const error: GatewayError = await response.json();
if (error.code === 'RATE_LIMIT_EXCEEDED') {
const retryAfter = response.headers.get('Retry-After');
throw new RateLimitError(error.error, retryAfter);
}
if (response.status === 404) {
throw new NotFoundError(error.error);
}
if (response.status === 400) {
throw new ValidationError(error.message || error.error);
}
throw new ApiError(error.message || error.error, error.code);
}interface FastAPIError {
detail:
| string
| Array<{
type: string;
loc: (string | number)[];
msg: string;
input?: unknown;
}>;
}
async function handleFastAPIError(response: Response): Promise<never> {
const error: FastAPIError = await response.json();
if (Array.isArray(error.detail)) {
// Validation errors
const messages = error.detail.map((e) => `${e.loc.join('.')}: ${e.msg}`);
throw new ValidationError(messages.join(', '));
}
throw new ApiError(error.detail);
}from typing import Dict, Any
class ApiError(Exception):
def __init__(self, message: str, code: str = None, request_id: str = None):
self.message = message
self.code = code
self.request_id = request_id
super().__init__(self.message)
def handle_gateway_error(response) -> None:
error_data = response.json()
error_message = error_data.get('error', 'Unknown error')
code = error_data.get('code')
request_id = error_data.get('requestId')
if code == 'RATE_LIMIT_EXCEEDED':
retry_after = response.headers.get('Retry-After')
raise RateLimitError(error_message, retry_after)
elif response.status_code == 404:
raise NotFoundError(error_message)
elif response.status_code == 400:
raise ValidationError(error_data.get('message', error_message))
else:
raise ApiError(error_message, code, request_id)from typing import Dict, Any, List, Union
class FastAPIError(Exception):
def __init__(self, detail: Union[str, List[Dict[str, Any]]]):
self.detail = detail
if isinstance(detail, str):
super().__init__(detail)
else:
messages = [f"{e['loc']}: {e['msg']}" for e in detail]
super().__init__('; '.join(messages))
def handle_fastapi_error(response) -> None:
error_data = response.json()
detail = error_data.get('detail')
if isinstance(detail, list):
# Validation errors
raise ValidationError(detail)
else:
raise FastAPIError(detail)Для следующих ошибок рекомендуется автоматический retry:
429 Too Many Requests— с задержкой из заголовкаRetry-After500 Internal Server Error— с экспоненциальной задержкой502 Bad Gateway— с экспоненциальной задержкой503 Service Unavailable— с экспоненциальной задержкой504 Gateway Timeout— с экспоненциальной задержкой
Для следующих ошибок не рекомендуется retry:
400 Bad Request— исправьте запрос401 Unauthorized— обновите токен403 Forbidden— проверьте права доступа404 Not Found— проверьте идентификаторы409 Conflict— разрешите конфликт422 Unprocessable Entity— исправьте валидационные ошибки
- API Reference
- CLI Reference
- Developer Guide - общая информация о разработке