Перейти к содержимому
Socialift
Разделы документации
Концепции

Обработка ошибок и автоматические повторы

Socialift SDK сводит ошибки всех платформ в одну иерархию: AuthError — невалидный токен, PermissionError — не хватает разрешений, RateLimitError — лимит, NotFoundError — объекта нет, TransportError — сетевой сбой. Ошибки лимитов, ответы HTTP 429 и 5xx и обрывы сети автоматически повторяются по RetryPolicy: по умолчанию 3 попытки, экспоненциальная задержка от 0,5 секунды и jitter.

Обновлено:

Какие ошибки перехватывать?

Сначала конкретные классы, общий ApiError — в конце. AuthError — отправьте пользователя переподключиться; PermissionError — исправьте scopes или пройдите App Review, повтор не поможет; RateLimitError — повторите позже с retry_after или своей задержкой; TransportError — проблема сети, обычно временная. Ошибки лицензии (LicenseError) — отдельная ветка, в ApiError не входят.

Иерархия ошибок и атрибуты

Иерархия ошибок и атрибуты — Таблица возможностей по платформам
КлассРодительАтрибутыЗначение
SocialiftErrorExceptionнетВсе ошибки SDK, включая лицензионные
ConfigurationErrorSocialiftErrorнетНе хватает настройки или она неверна (например, пустой app_id); возникает до отправки запроса
ApiErrorSocialiftErrormessage, provider, status, code, subcode, payload, urlAPI платформы вернул ошибку
AuthErrorApiErrorкак у ApiErrorТокен невалиден, истёк или отозван
PermissionErrorApiErrorкак у ApiErrorНе хватает разрешения (scope), App Review или прав в чате
RateLimitErrorApiErrorApiError + retry_after (секунды или None)Лимит запросов — нужно подождать и повторить
NotFoundErrorApiErrorкак у ApiErrorОбъекта нет или он не виден владельцу токена
TransportErrorSocialiftErrorurlОбрыв соединения, DNS или таймаут — HTTP-статуса нет
LicenseErrorSocialiftErrorнетОшибки лицензии — см. страницу «Аутентификация»

естьнетТаблицу можно прокрутить вбок

Примечания и ограничения

socialift.PermissionError совпадает по имени со встроенным PermissionError Python — импортируйте с псевдонимом: from socialift import PermissionError as ScopeError. Формат str(exc): [provider] сообщение (HTTP status, code=...).

В какой класс попадает ошибка платформы?

SDK классифицирует ошибки по этим правилам; всё, что не подошло, остаётся обычным ApiError.

В какой класс попадает ошибка платформы? — Таблица возможностей по платформам
КлассMeta (Facebook, Instagram, Ads)LinkedInTikTokTelegram Bot API
RateLimitErrorcode 4, 17, 32, 613 или HTTP 429HTTP 429rate_limit_exceeded, spam_risk_too_many_posts, spam_risk или HTTP 429HTTP 429 или parameters.retry_after в ответе
AuthErrorcode 190, 102 или HTTP 401HTTP 401access_token_invalid, access_token_expired, invalid_access_token, token_not_found или HTTP 401HTTP 401 или «unauthorized» в описании
PermissionErrorcode 10, 200–299 или HTTP 403HTTP 403scope_not_authorized, scope_permission_missed, unaudited_client_can_only_post_to_private_accounts, url_ownership_unverified, spam_risk_user_banned_from_posting или HTTP 403HTTP 403 или «forbidden» в описании (например, пользователь заблокировал бота)
NotFoundErrorcode 803 или HTTP 404HTTP 404publish_id_not_found, video_not_found или HTTP 404HTTP 404 или «not found» в описании
Примечания и ограничения

Порядок проверки: лимит → auth → разрешения → не найдено. У Meta exc.code — это error.code, exc.subcode — error_subcode, сообщение берётся из error_user_msg (если есть) или message. У LinkedIn exc.code — serviceErrorCode. У TikTok строковый код важнее HTTP-статуса, exc.code остаётся пустым, исходный код — в exc.payload, а log_id добавляется в текст сообщения. У Telegram exc.code — error_code, а токен бота в exc.url маскируется.

Как переводятся ошибки аккаунта Telegram (MTProto)?

TelegramAccount переводит исключения Telethon в ту же иерархию, поэтому один блок except работает и для бота, и для аккаунта, и для других платформ.

RateLimitError
FloodWaitError и другие ошибки Flood…; code=420, retry_after — секунды, названные Telegram. SDK сам не ждёт: решение за вами, чтобы 20-минутное ожидание не заморозило приложение.
AuthError
AuthKeyUnregisteredError, SessionRevokedError, SessionExpiredError, UserDeactivatedError, AuthKeyDuplicatedError, UnauthorizedError — сессия невалидна, аккаунт нужно переподключить (status=401).
PermissionError
ChatAdminRequiredError, ChatWriteForbiddenError, UserBannedInChannelError, ChannelPrivateError, UserPrivacyRestrictedError, MessageDeleteForbiddenError, AdminsTooMuchError, UserNotParticipantError, ChatRestrictedError (status=403).
NotFoundError
UsernameNotOccupiedError, PeerIdInvalidError, MessageIdInvalidError, ChannelInvalidError, UserIdInvalidError, InviteHashInvalidError и ValueError, который Telethon бросает, не найдя объект (status=404).
TransportError
ConnectionError, OSError, TimeoutError — связь с Telegram прервалась.

Что означают коды ошибок Meta?

Ошибка Meta Graph API приходит в объекте error: message, type, code, error_subcode, error_user_title, error_user_msg, fbtrace_id. SDK сохраняет весь ответ в exc.payload — там же fbtrace_id, который нужен при обращении в поддержку Meta.

По документации Meta: 4 — лимит на уровне приложения, 17 — на уровне пользователя, 32 — на уровне страницы в Pages API, 613 — отдельный лимит endpoint; 190 — access token истёк или невалиден, 102 — сессия API; 10 — разрешение не выдано или отозвано, 200–299 — ошибки конкретных разрешений.

Стандартный заголовок Retry-After для лимитов Meta не документирует; для лимитов Business Use Case ориентировочное время ожидания приходит в поле estimated_time_to_regain_access заголовка X-Business-Use-Case-Usage (в минутах). Поэтому у RateLimitError от Meta retry_after обычно None — задержку задавайте сами.

Какие ошибки повторяются автоматически?

В клиентах Facebook, Instagram, Ads, LinkedIn, TikTok и Telegram SDK повторяет запрос в трёх случаях: RateLimitError; ApiError с HTTP 429, 500, 502, 503 или 504; TransportError (ошибки соединения aiohttp и таймауты). AuthError, PermissionError, NotFoundError и прочие 4xx поднимаются сразу. Когда попытки заканчиваются, поднимается последняя ошибка.

Задержка: если провайдер прислал заголовок Retry-After, SDK ждёт ровно столько — это значение не ограничивается backoff_max. Иначе работает формула RetryPolicy. Каждый повтор после HTTP-ошибки пишется в логгер socialift с уровнем WARNING.

Исключения: если TikTok вернул ошибку в теле ответа с HTTP 200, она поднимается без повторов. TelegramAccount (MTProto) RetryPolicy не использует: FloodWaitError сразу становится RateLimitError, а попытки подключения управляются параметром connection_retries.

Таймауты и ошибки соединения повторяются и для POST-запросов. Если запрос дошёл до платформы, а ответ потерялся, действие может выполниться дважды — для операций записи, где повтор опасен, используйте отдельный клиент с RetryPolicy(attempts=1).

Значения RetryPolicy по умолчанию

Значения RetryPolicy по умолчанию — Таблица возможностей по платформам
ПараметрПо умолчаниюЗначение
attempts3Общее число попыток, включая первую
backoff_base0.5Основа первой задержки, секунды
backoff_max30.0Верхняя граница задержки (до jitter), секунды
jitterTrueУмножает задержку на случайный коэффициент 0,5–1,5
timeout (параметр клиента)30.0Общий таймаут одного HTTP-запроса, секунды
Примечания и ограничения

Формула: min(backoff_base × 2^(n−1), backoff_max), затем jitter. С настройками по умолчанию после первой ошибки ожидание около 0,25–0,75 с, после второй — 0,5–1,5 с, третья ошибка поднимается.

Как передать свою RetryPolicy?

retry.py
import os
from socialift import Facebook, RetryPolicy, Telegram

# Для фоновых задач: больше попыток, длиннее задержка и таймаут
patient = RetryPolicy(attempts=5, backoff_base=1.0, backoff_max=60.0)
fb = Facebook.from_env(retry=patient, timeout=60.0)

# Для операций записи, где повтор опасен: без повторов
once = RetryPolicy(attempts=1)
bot = Telegram(token=os.environ["TELEGRAM_BOT_TOKEN"], retry=once)

retry= и timeout= принимают все HTTP-клиенты (Facebook, Instagram, LinkedIn, TikTok, Telegram, Ads), а также их from_env() и Instagram.via_facebook(). Политика задаётся для каждого клиента отдельно — глобальной настройки нет.

Рекомендуемая обработка: четыре случая

Когда повторы исчерпаны, ошибка доходит до вашего кода. Ниже — шаблон для фоновой задачи.

handle_errors.py
import logging
from socialift import ApiError, AuthError, RateLimitError, TransportError
from socialift import PermissionError as ScopeError

log = logging.getLogger("app")


async def sync_profile(ig, account, jobs):
    # account и jobs — объекты вашего приложения (запись в БД и очередь задач)
    try:
        return await ig.profile(account.token, ig_user_id=account.ig_user_id)
    except AuthError:
        account.needs_reconnect = True                 # отправьте пользователя в OAuth заново
    except ScopeError as exc:
        log.error("Не хватает разрешений: %s", exc)    # scope или App Review — повтор бесполезен
    except RateLimitError as exc:
        await jobs.retry_later(account.id, delay=exc.retry_after or 300)
    except TransportError:
        await jobs.retry_later(account.id, delay=30)
    except ApiError as exc:
        log.error("%s status=%s code=%s", exc.provider, exc.status, exc.code)

Порядок except важен: AuthError, PermissionError и RateLimitError — наследники ApiError, поэтому идут раньше.

SDK не обновляет истёкший токен сам. Методы обновления: Instagram.refresh_token (Instagram Login), TikTok.refresh_token, LinkedIn.refresh; при отозванном токене пользователь входит заново.

Чек-лист по обработке ошибок

  • Не повторяйте AuthError и PermissionError — они требуют переподключения или исправления настроек.
  • Если у RateLimitError нет retry_after, ставьте задачу в очередь с задержкой в минутах.
  • Для логов используйте str(exc), exc.status, exc.code и exc.payload. Не пишите в лог exc.url: в запросах Meta там есть query-параметр access_token.
  • Перехватывайте LicenseError отдельно от ApiError — это проблема лицензии, а не платформы.
  • ConfigurationError — ошибка в коде или переменных окружения; выявляйте её при старте.

Частые вопросы

Сколько ждать, если у RateLimitError retry_after равен None?

Для Meta это обычная ситуация: стандартный заголовок Retry-After для лимитов Meta не документирует. Выберите задержку сами (например, несколько минут) и перезапустите задачу через очередь. Встроенные повторы SDK измеряются секундами и не рассчитаны на выход из длительного лимита.

Обновляет ли SDK токен сам после AuthError?

Нет. SDK не хранит токены и не обновляет их автоматически. Обновить токен до истечения срока или отправить пользователя в OAuth заново — задача вашего приложения. TokenBundle.is_expiring() помогает понять, когда пора обновлять.

Почему PermissionError не проходит при повторе?

Потому что причина не в запросе, а в разрешениях: нужный scope не запрошен, приложение не прошло проверку платформы (например, Meta App Review) или в чате Telegram нет прав. Исправьте настройки и переподключите пользователя с нужными разрешениями.

Можно ли полностью отключить повторы?

Да: передайте клиенту retry=RetryPolicy(attempts=1). Тогда любая ошибка поднимается сразу после первой попытки. Это полезно для операций, где повтор опасен, — публикации поста или отправки сообщения.

Где взять код ошибки TikTok?

TikTok возвращает строковый код (например, access_token_invalid). SDK превращает его в класс, но не записывает в exc.code: исходный код лежит в exc.payload, а log_id, который запрашивает поддержка TikTok, добавлен в текст сообщения.

Чем TransportError отличается от ApiError?

ApiError — платформа ответила, но ошибкой: есть status и часто code. TransportError — ответа не было вовсе (обрыв, DNS, таймаут), поэтому status нет. TransportError повторяется автоматически, а ApiError — только при лимите, 429 и 5xx.

Источники

  1. Meta: Graph API error handling
  2. Meta: Graph API rate limiting
  3. LinkedIn API error handling
  4. TikTok API v2 error handling
  5. Telegram Bot API

Связанные страницы