Обработка ошибок в iOS SDK

В Adapty SDK есть собственная обёртка для всех типов ошибок — AdaptyError. По сути, каждая ошибка, возвращаемая SDK, является AdaptyError. У неё есть два полезных свойства: originalError и adaptyErrorCode, описанные ниже.

originalError содержит исходную ошибку на случай, если она вам нужна для работы. Это может быть SKError, NSError или обычная Swift Error. Свойство опциональное — некоторые ошибки генерируются напрямую SDK (например, при несогласованных или отсутствующих данных) и не имеют исходной ошибки, вокруг которой изначально строился враппер.

adaptyErrorCode используется для обработки типичных проблем, например:

  • недействительные учётные данные
  • сетевые ошибки
  • отменённые платежи
  • проблемы с выставлением счёта
  • недействительный чек
  • и многое другое

Проверить ошибку на конкретный код и отреагировать соответствующим образом очень просто.

do {
    let info = try await Adapty.makePurchase(product: product)
} catch {
    if error.adaptyErrorCode == .paymentCancelled {
        // purchase was cancelled
        // you can offer discount to your user or remind them later
    }
}
Tip

Включите подробные логи перед отладкой. Большинство AdaptyError оборачивают ошибку StoreKit, сети или бэкенда. Если включить подробные логи (Adapty.logLevel = .verbose — см. Логирование), эта вложенная ошибка выводится в консоль, и обычно сразу становится ясна реальная причина. Свойство originalError заполняется в любом случае — подробные логи просто делают её видимой в консоли.

Important

Если эти решения не помогли, перейдите в раздел Другие проблемы — там описаны шаги, которые стоит выполнить перед обращением в поддержку, чтобы мы могли помочь вам быстрее.

Ошибки StoreKit

ОшибкаКодРешение
unknown0Код ошибки, указывающий на неизвестную или непредвиденную ошибку.
Повторите попытку или обратитесь к разделу Другие проблемы.
clientInvalid1Код ошибки, указывающий на то, что клиенту не разрешено выполнять запрошенное действие.
paymentCancelled2

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

Никаких действий не требуется, однако с точки зрения бизнес-логики вы можете предложить пользователю скидку или напомнить об оплате позже.

paymentInvalid3Ошибка указывает на то, что один из параметров платежа не был распознан App Store.
paymentNotAllowed4Код ошибки, указывающий на то, что пользователю не разрешено авторизовывать платежи.
storeProductNotAvailable5Код ошибки, указывающий на то, что запрошенный продукт недоступен в сторе.
Попробуйте переустановить приложение.
cloudServicePermissionDenied6Код ошибки, указывающий на то, что пользователь не разрешил доступ к информации об облачном сервисе.
cloudServiceNetworkConnectionFailed7Код ошибки, указывающий на то, что устройству не удалось подключиться к сети.
cloudServiceRevoked8Код ошибки, указывающий на то, что пользователь отозвал разрешение на использование этого облачного сервиса.
privacyAcknowledgementRequired9Код ошибки, указывающий на то, что пользователь ещё не принял политику конфиденциальности Apple.
unauthorizedRequestData10Код ошибки, указывающий на то, что приложение пытается использовать свойство, для которого у него нет необходимого разрешения.
invalidOfferIdentifier11

Идентификатор предложения недействителен. Например, вы не создали предложение с таким идентификатором в App Store или отозвали его.

Убедитесь, что нужные предложения настроены в AppStore Connect, и передайте корректный идентификатор предложения.

invalidSignature12Код ошибки, указывающий на то, что подпись в скидке на оплату недействительна.
missingOfferParams13Код ошибки, указывающий на то, что в скидке на оплату отсутствуют параметры.
invalidOfferPrice14Код ошибки, указывающий на то, что цена, указанная вами в App Store Connect, больше не действительна. Предложения всегда должны представлять сниженную цену.
noProductIDsFound1000

Ошибка указывает на то, что ни один из продуктов, запрошенных на пейволе, недоступен для покупки в App Store, хотя они там и перечислены. Иногда эта ошибка сопровождается предупреждением InvalidProductIdentifiers. Если предупреждение появляется без ошибки — игнорируйте его.

Если вы сталкиваетесь с этой ошибкой, следуйте инструкциям в разделе Исправление ошибки Code-1000 noProductIDsFound.

productRequestFailed1002Не удалось получить список доступных продуктов в данный момент.
cantMakePayments1003Встроенные покупки не разрешены на этом устройстве. См. гайд по устранению неполадок.
cantReadReceipt1005

На устройстве нет действительного чека. Это может быть проблемой при тестировании в песочнице.

В песочнице действительный файл чека появляется только после реальной покупки, поэтому убедитесь, что совершили хотя бы одну перед обращением к нему. При тестировании в песочнице также убедитесь, что вошли на устройство с действительным аккаунтом Apple sandbox.

productPurchaseFailed1006Покупка продукта не удалась. Это обёртка над базовой ошибкой StoreKit — прочитайте originalError (или включите подробные логи, чтобы увидеть её в консоли) для выяснения причины. Обёрнутая ошибка, как правило, соответствует одному из кодов StoreKit 0–14 из таблицы выше — чаще всего это paymentCancelled, paymentInvalid, paymentNotAllowed или invalidOfferPrice. Если конкретную причину определить не удаётся, попробуйте создать новый профиль песочницы; если проблема сохраняется, обратитесь в поддержку Apple.
refreshReceiptFailed1010Операция обновления чека завершилась ошибкой.
fetchSubscriptionStatusFailed1020Не удалось получить статус подписки из App Store.
unknownTransactionId1030Идентификатор транзакции неизвестен.
paymentPendingError1050Платёж в настоящее время ожидает обработки.
billingPlanUnavailable1060Продукт не поддерживает запрошенный тарифный план на этом устройстве. Для плана с 12-месячным обязательством требуется iOS 26.4 или новее и приложение, собранное в Xcode 26.5 или новее.

Сетевые ошибки

ОшибкаКодРешение
notActivated2002SDK Adapty не активирован.
Чаще всего возникает, когда splash-экран или ранний UI-хук вызывает методы Adapty до завершения Adapty.activate. Симптом нестабильный и может не воспроизводиться на симуляторе, поскольку тайминги на реальном устройстве отличаются. Дождитесь завершения activate через completion handler или async-результат, прежде чем делать любые другие вызовы SDK. Полная последовательность описана в Порядок вызовов в iOS SDK.
badRequest2003Некорректный запрос.
При вызове getPaywall это чаще всего означает, что запрошенный плейсмент не существует в приложении, которому принадлежит ваш API-ключ. Убедитесь, что ID плейсмента скопирован точно и что API-ключ и плейсмент относятся к одному приложению в дашборде Adapty.
serverError2004Ошибка сервера.
Повторите попытку через некоторое время. Если проблема не исчезает, обратитесь в службу поддержки Adapty.
Этот код также покрывает троттлинг: если вы слишком часто обращаетесь к одному и тому же эндпоинту (например, часто обновляете профиль), сервер отвечает кодом 429, и SDK блокирует этот эндпоинт до истечения интервала повтора.
networkFailed2005Ошибка указывает на проблемы с сетевым подключением на устройстве пользователя.
Попробуйте отключить VPN или переключиться с мобильной сети на Wi-Fi или наоборот.
decodingFailed2006Ошибка указывает на сбой декодирования ответа — SDK получил данные, которые не может разобрать.
Если она возникает при загрузке локального файла резервного пейвола, файл устарел относительно ожиданий SDK: скачайте свежий файл со страницы Placements. Несовпадение версий резервного пейвола также может проявляться как ошибка 3001.
encodingFailed2009Ошибка указывает на сбой кодирования запроса.

Общие ошибки

ОшибкаКодРешение
analyticsDisabled3000Обработка аналитических событий невозможна, так как вы отключили её.
wrongParam3001Ошибка указывает на некорректные параметры.
Если вы используете старый Paywall Builder и не можете отобразить пейвол из-за этой ошибки, включите Show on device в настройках билдера.
Другая возможная причина — версия локального файла резервного пейвола не совпадает с версией SDK. Скачайте новый файл в дашборде.
activateOnceError3005Метод .activate нельзя вызывать более одного раза.
profileWasChanged3006Профиль пользователя был изменён во время операции.
Это происходит, когда метод вызывается во время выполнения Adapty.identify — вызов попадает на профиль, который вот-вот будет заменён, и SDK отклоняет его. Всегда дожидайтесь завершения identify (через await или обработчик завершения) перед любым пользовательским вызовом. См. Порядок вызовов в iOS SDK.
unsupportedData3007Ошибка указывает на то, что формат данных не поддерживается SDK.
unidentifiedUserLogout3020Вызов метода logout для неидентифицированного пользователя невозможен.
fetchTimeoutError3101Ошибка указывает на истечение времени ожидания операции fetch.
operationInProgress3201Другая операция того же типа ещё выполняется.
Возвращается методом showStoreMessages, если предыдущий вызов всё ещё показывает сообщения App Store. Дождитесь завершения и попробуйте снова.
resolverFailure3202SDK не удалось найти ресурс, необходимый для операции.
Возвращается методом showStoreMessages из UIKit, если вы не передали window scene и нет активной сцены переднего плана. Передайте сцену явно или вызовите метод повторно, когда приложение будет на переднем плане.
operationInterrupted9000Операция была прервана системой.

Медленная загрузка сразу после updateProfile

Если вы задаёте пользовательские атрибуты через updateProfile и запрашиваете плейсмент в той же сессии, SDK может вычислить хеш сегмента для плейсмента на основе атрибутов, которые ещё не успели примениться. SDK повторяет запрос после обновления хеша сегмента, поэтому симптом проявляется как замедленная загрузка, а не ошибка. Загрузка завершается неудачей только в том случае, если после повторной попытки расхождение сохраняется — это означает, что запись атрибута не прошла.

Чтобы избежать повторного запроса, дождитесь завершения updateProfile перед загрузкой плейсмента. Подробнее — в разделе Порядок вызовов в iOS SDK.

Другие проблемы

Если вы ещё не нашли решение, попробуйте следующее:

  • Обновите SDK до последней версии: мы всегда рекомендуем использовать актуальные версии SDK — они более стабильны и содержат исправления известных проблем.
  • Обратитесь в службу поддержки или получите помощь от других разработчиков на форуме поддержки.
  • Напишите в поддержку на support@adapty.io или в чат: если вы не готовы обновлять SDK или обновление не помогло, свяжитесь с нашей командой поддержки. Обратите внимание: проблема решится быстрее, если вы включите подробное логирование и поделитесь логами с командой. Также можно прикрепить соответствующие фрагменты кода.