SDK

Обработка ошибок

Справочник по ConnectorError — структурированные ошибки с кодами, автоматическое определение повторяемости и лучшие практики для надёжных коннекторов.

Обработка ошибок

Класс ConnectorError обеспечивает структурированное сообщение об ошибках с кодами, которые движок выполнения использует для определения поведения при повторных попытках, уведомлений пользователя и переходов состояния пайплайна.

ConnectorError

import { ConnectorError } from "@triggo/connector-sdk";
import { CONNECTOR_ERROR_CODES } from "@triggo/shared";

throw new ConnectorError(
  CONNECTOR_ERROR_CODES.UPSTREAM_ERROR,
  "Service returned 503",
  originalError, // optional cause
);

Конструктор

class ConnectorError extends Error {
  readonly code: ConnectorErrorCode;
  readonly retryable: boolean;

  constructor(code: ConnectorErrorCode, message: string, cause?: unknown);
}
ПараметрТипОбязательноОписание
codeConnectorErrorCodeДаОдин из семи кодов ошибок (см. ниже).
messagestringДаЧитаемое сообщение об ошибке. Отображается в логах выполнения.
causeunknownНетИсходная ошибка для отладки. Передаётся в Error.cause.

Свойство retryable устанавливается автоматически на основе кода ошибки.

Коды ошибок

Все коды ошибок определены в @triggo/shared:

import { CONNECTOR_ERROR_CODES } from "@triggo/shared";
КодЗначениеПовторяемыйКогда использовать
RATE_LIMITED"RATE_LIMITED"ДаВнешний API вернул HTTP 429 или аналогичный ответ об ограничении частоты запросов.
AUTH_EXPIRED"AUTH_EXPIRED"НетУчётные данные аутентификации недействительны или истекли. Запускает поток повторной аутентификации.
NOT_FOUND"NOT_FOUND"НетЗапрашиваемый ресурс не существует (HTTP 404).
VALIDATION_ERROR"VALIDATION_ERROR"НетВходные данные не прошли валидацию. Пользователю необходимо исправить конфигурацию.
TIMEOUT"TIMEOUT"ДаВнешний API не ответил в пределах окна тайм-аута.
UPSTREAM_ERROR"UPSTREAM_ERROR"ДаВнешний сервис вернул серверную ошибку (HTTP 5xx) или недоступен.
UNKNOWN"UNKNOWN"НетНепредвиденная ошибка, не подходящая под другие категории.

Повторяемые ошибки

Три кода ошибок автоматически помечаются как повторяемые:

const RETRYABLE_ERROR_CODES: ReadonlySet<ConnectorErrorCode> = new Set([
  "RATE_LIMITED",
  "TIMEOUT",
  "UPSTREAM_ERROR",
]);

Когда выбрасывается повторяемая ошибка и у действия настроен errorHandlingOptions.retryOnFailure, движок выполнения автоматически повторяет попытку с экспоненциальным откатом.

ErrorHandlingOptions

Настройка поведения при повторах и ошибках для каждого действия:

import { createAction } from "@triggo/connector-sdk";

const myAction = createAction({
  name: "send_notification",
  displayName: "Send Notification",
  description: "Sends a push notification.",
  props: {},
  errorHandlingOptions: {
    retryOnFailure: {
      maxRetries: 3,
      baseIntervalMs: 1000,
    },
    continueOnFailure: false,
  },
  async run(context) {
    // ...
  },
});
ПолеТипОписание
retryOnFailure.maxRetriesnumberМаксимальное количество повторных попыток для повторяемых ошибок.
retryOnFailure.baseIntervalMsnumberБазовая задержка в мс. Фактическая задержка использует экспоненциальный откат.
continueOnFailurebooleanЕсли true, последующие узлы пайплайна выполняются даже при ошибке этого действия.

Паттерны использования

Обработка HTTP-ответов

import { ConnectorError } from "@triggo/connector-sdk";
import { CONNECTOR_ERROR_CODES } from "@triggo/shared";

async function handleResponse(response: Response): Promise<unknown> {
  if (response.ok) {
    return response.json();
  }

  if (response.status === 401 || response.status === 403) {
    throw new ConnectorError(
      CONNECTOR_ERROR_CODES.AUTH_EXPIRED,
      `Authentication failed: ${response.status}`,
    );
  }

  if (response.status === 404) {
    throw new ConnectorError(
      CONNECTOR_ERROR_CODES.NOT_FOUND,
      "Resource not found",
    );
  }

  if (response.status === 429) {
    throw new ConnectorError(
      CONNECTOR_ERROR_CODES.RATE_LIMITED,
      "Rate limit exceeded",
    );
  }

  if (response.status >= 500) {
    throw new ConnectorError(
      CONNECTOR_ERROR_CODES.UPSTREAM_ERROR,
      `Server error: ${response.status} ${response.statusText}`,
    );
  }

  throw new ConnectorError(
    CONNECTOR_ERROR_CODES.UNKNOWN,
    `Unexpected response: ${response.status}`,
  );
}

Обработка сетевых ошибок

async function safeFetch(url: string, options: RequestInit): Promise<Response> {
  try {
    return await fetch(url, options);
  } catch (error) {
    if (error instanceof TypeError && (error.message.includes("fetch") || error.message.includes("network"))) {
      throw new ConnectorError(
        CONNECTOR_ERROR_CODES.UPSTREAM_ERROR,
        "Network error: unable to reach the service",
        error,
      );
    }

    if (error instanceof DOMException && error.name === "AbortError") {
      throw new ConnectorError(
        CONNECTOR_ERROR_CODES.TIMEOUT,
        "Request timed out",
        error,
      );
    }

    throw new ConnectorError(
      CONNECTOR_ERROR_CODES.UNKNOWN,
      "Unexpected error during request",
      error,
    );
  }
}

Валидация входных данных

async run(context) {
  const email = context.propsValue.email as string;

  if (!email.includes("@")) {
    throw new ConnectorError(
      CONNECTOR_ERROR_CODES.VALIDATION_ERROR,
      `Invalid email address: "${email}"`,
    );
  }

  // proceed with valid input...
}

Лучшие практики

  • Всегда используйте ConnectorError вместо обычного Error -- движок выполнения трактует нераспознанные ошибки как UNKNOWN
  • Выбирайте наиболее специфичный код ошибки -- AUTH_EXPIRED запускает повторную аутентификацию, RATE_LIMITED учитывает заголовки retry-after
  • Включайте полезный контекст в сообщение -- коды статуса, идентификаторы ресурсов и имена эндпоинтов помогают при отладке
  • Передавайте исходную ошибку как cause для сохранения стека вызовов
  • Устанавливайте continueOnFailure: true только для некритичных действий (логирование, аналитика, опциональные уведомления)
  • Настраивайте retryOnFailure для действий, обращающихся к ненадёжным внешним сервисам

On this page