Обработка ошибок
Справочник по 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);
}| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
code | ConnectorErrorCode | Да | Один из семи кодов ошибок (см. ниже). |
message | string | Да | Читаемое сообщение об ошибке. Отображается в логах выполнения. |
cause | unknown | Нет | Исходная ошибка для отладки. Передаётся в 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.maxRetries | number | Максимальное количество повторных попыток для повторяемых ошибок. |
retryOnFailure.baseIntervalMs | number | Базовая задержка в мс. Фактическая задержка использует экспоненциальный откат. |
continueOnFailure | boolean | Если 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для действий, обращающихся к ненадёжным внешним сервисам
Контекст и хранилище
Справочник по ActionContext и TriggerContext — объекты контекста выполнения, предоставляющие аутентификацию, значения свойств, персистентное хранилище и данные вебхуков.
Полный пример
Пошаговое руководство по созданию полного коннектора с нуля — сервис погодных оповещений с аутентификацией SecretText, одним действием и одним webhook-триггером.