Skip to content

Latest commit

 

History

History
544 lines (415 loc) · 27.9 KB

File metadata and controls

544 lines (415 loc) · 27.9 KB

Error Handling — Accellens

Версия: 1.1 Дата обновления: 17 ноября 2025


1. Обзор

Accellens API использует стандартизированный формат обработки ошибок для обеспечения консистентности и удобства отладки. Все ошибки возвращаются в едином формате с кодами ошибок, сообщениями и дополнительными деталями.


2. Формат ответа об ошибке

2.1 Формат Gateway (Node.js)

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"
}

2.2 Формат Python Services (FastAPI)

Python сервисы возвращают ошибки в стандартном формате FastAPI:

{
  "detail": "Human-readable error message"
}

Для валидационных ошибок (422):

{
  "detail": [
    {
      "type": "string_type",
      "loc": ["body", "field_name"],
      "msg": "Error message",
      "input": "invalid_value"
    }
  ]
}

2.2 HTTP статус коды

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

3. Коды ошибок и сообщения

3.1 Коды ошибок Gateway

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 Неизвестная ошибка

3.2 Сообщения об ошибках Python Services

Python сервисы возвращают детальные сообщения в поле detail. Ниже приведены примеры реальных сообщений:

3.2.1 Пользователи (Users)

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 Пользователь не найден

3.2.2 Проекты (Projects)

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 Проект не найден

3.2.3 Интеграции (Integrations)

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 не найден

3.2.4 Webhooks

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 не найден

3.2.5 Runs (Сканирования)

HTTP Status Сообщение Контекст
400 Invalid ID format Некорректный формат ID
404 Run not found Run не найден
403 Actor does not have access to this project Нет доступа к проекту

3.2.6 API Keys

HTTP Status Сообщение Контекст
400 Invalid ID format Некорректный формат ID
404 API key not found API ключ не найден
400 Cannot rotate inactive API key Нельзя ротировать неактивный ключ

3.2.7 Reports

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

3.3 Аутентификация и авторизация (Legacy коды)

Код 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 ключ

3.2 Проекты

Код 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 Доступ к проекту запрещён Проверьте права доступа к проекту

3.3 Сканирования

Код 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 Сканирование отменено Запустите новое сканирование

3.4 Валидация

Код HTTP Status Описание Решение
VALIDATION_ERROR 422 Ошибка валидации Проверьте формат данных запроса
VALIDATION_FIELD_REQUIRED 422 Обязательное поле отсутствует Укажите все обязательные поля
VALIDATION_FIELD_INVALID 422 Некорректное значение поля Проверьте формат и допустимые значения
VALIDATION_FIELD_TOO_LONG 422 Поле превышает максимальную длину Уменьшите длину поля
VALIDATION_FIELD_TOO_SHORT 422 Поле меньше минимальной длины Увеличьте длину поля

3.5 Форматы и экспорт

Код HTTP Status Описание Решение
UNSUPPORTED_FORMAT 422 Неподдерживаемый формат Используйте один из поддерживаемых форматов: json, pdf, sarif (в MVP/v1). allure планируется для v2+
EXPORT_FAILED 500 Ошибка экспорта Повторите запрос позже
EXPORT_NOT_READY 202 Экспорт ещё не готов Дождитесь завершения экспорта

3.6 Ассистивные технологии

Код HTTP Status Описание Решение
ASSISTIVE_DISABLED 422 Ассистивная симуляция отключена Включите симуляцию в настройках проекта
ASSISTIVE_NOT_SUPPORTED 422 Ассистивная технология не поддерживается Используйте поддерживаемую технологию
ASSISTIVE_SIMULATION_FAILED 500 Ошибка симуляции Повторите запрос позже

3.7 Rate Limiting

Код HTTP Status Описание Решение
RATE_LIMIT_EXCEEDED 429 Превышен лимит запросов Дождитесь сброса лимита (см. заголовок Retry-After)
RATE_LIMIT_QUOTA_EXCEEDED 429 Превышена квота запросов Обновите план подписки

3.8 Внутренние ошибки

Код HTTP Status Описание Решение
INTERNAL_ERROR 500 Внутренняя ошибка сервера Повторите запрос позже или обратитесь в поддержку
SERVICE_UNAVAILABLE 503 Сервис временно недоступен Повторите запрос позже
UPSTREAM_ERROR 502 Ошибка upstream сервиса Повторите запрос позже
DATABASE_ERROR 500 Ошибка базы данных Повторите запрос позже или обратитесь в поддержку

4. Примеры ответов

4.1 Ошибка валидации (FastAPI)

{
  "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

4.1.1 Ошибка валидации (Gateway)

{
  "error": "Bad Request",
  "message": "Validation failed: slug must match pattern [a-z0-9-]+",
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

HTTP Status: 400 Bad Request

4.2 Ресурс не найден (Gateway)

{
  "error": "Not found",
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

HTTP Status: 404 Not Found

4.2.1 Ресурс не найден (FastAPI)

{
  "detail": "Project not found"
}

HTTP Status: 404 Not Found

4.3 Rate Limit (Gateway)

{
  "error": "Rate limit exceeded",
  "code": "RATE_LIMIT_EXCEEDED",
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

HTTP Status: 429 Too Many Requests Заголовки:

  • X-RateLimit-Limit: 200
  • X-RateLimit-Remaining: 0
  • X-RateLimit-Reset: 1699603200
  • Retry-After: 60

4.3.1 Rate Limit (FastAPI)

{
  "detail": "Rate limit exceeded. Maximum 200 requests per minute"
}

HTTP Status: 429 Too Many Requests

4.4 Внутренняя ошибка (Gateway)

{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred",
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

HTTP Status: 500 Internal Server Error

4.4.1 Внутренняя ошибка (FastAPI)

{
  "detail": "Internal server error"
}

HTTP Status: 500 Internal Server Error


5. Трейсинг ошибок

5.1 Request ID (Gateway)

Все ответы об ошибках от Gateway содержат requestId для трейсинга запроса в логах системы.

5.2 Заголовок X-Request-Id

Клиенты могут передавать собственный X-Request-Id для корреляции запросов:

X-Request-Id: my-custom-request-id-123

Gateway вернёт этот же ID в ответе:

{
  "error": "Not found",
  "requestId": "my-custom-request-id-123"
}

5.3 Трейсинг в Python Services

Python сервисы используют OpenTelemetry для трейсинга. Request ID передаётся через заголовки и логируется в структурированных логах.


6. Обработка ошибок на клиенте

6.1 TypeScript пример (Gateway)

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);
}

6.1.1 TypeScript пример (FastAPI)

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);
}

6.2 Python пример (Gateway)

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)

6.2.1 Python пример (FastAPI)

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)

7. Retry стратегии

7.1 Автоматический retry

Для следующих ошибок рекомендуется автоматический retry:

  • 429 Too Many Requests — с задержкой из заголовка Retry-After
  • 500 Internal Server Error — с экспоненциальной задержкой
  • 502 Bad Gateway — с экспоненциальной задержкой
  • 503 Service Unavailable — с экспоненциальной задержкой
  • 504 Gateway Timeout — с экспоненциальной задержкой

7.2 Не рекомендуется retry

Для следующих ошибок не рекомендуется retry:

  • 400 Bad Request — исправьте запрос
  • 401 Unauthorized — обновите токен
  • 403 Forbidden — проверьте права доступа
  • 404 Not Found — проверьте идентификаторы
  • 409 Conflict — разрешите конфликт
  • 422 Unprocessable Entity — исправьте валидационные ошибки

8. Ссылки