Gestión de errores en el SDK de iOS
El SDK de Adapty tiene su propio contenedor para todo tipo de errores, llamado AdaptyError. Básicamente, todo error que devuelve el SDK es un AdaptyError. Tiene dos propiedades útiles: originalError y adaptyErrorCode, que se describen a continuación.
originalError contiene el error original en caso de que necesites trabajar directamente con él. Puede ser SKError, NSError o simplemente un Error genérico de Swift. Esta propiedad es opcional, ya que algunos errores pueden ser generados directamente por el SDK —como datos inconsistentes o faltantes— y no tendrán un error original sobre el que se construyó el wrapper.
adaptyErrorCode se puede usar para gestionar problemas comunes, como:
- credenciales no válidas
- errores de red
- pagos cancelados
- problemas de facturación
- recibo no válido
- y mucho más
Es bastante sencillo comprobar el error buscando códigos específicos y reaccionar en consecuencia.
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
}
}
Activa los logs detallados antes de depurar. La mayoría de los AdaptyError envuelven un error subyacente de StoreKit, de red o del backend. Con los logs detallados activados (Adapty.logLevel = .verbose — consulta Logging), ese error envuelto se imprime en la consola, lo que normalmente indica la causa real. La propiedad originalError se rellena independientemente del nivel de log — los logs detallados simplemente lo muestran en la consola.
Si estas soluciones no resuelven tu problema, consulta Otros problemas para conocer los pasos a seguir antes de contactar con el soporte y así ayudarnos a asistirte de forma más eficiente.
Errores de StoreKit
| Error | Código | Solución |
|---|---|---|
| unknown | 0 | Código de error que indica que ocurrió un error desconocido o inesperado. Vuelve a intentarlo o consulta la sección Otros problemas. |
| clientInvalid | 1 | Este código de error indica que el cliente no tiene permiso para realizar la acción intentada. |
| paymentCancelled | 2 | Este código de error indica que el usuario canceló una solicitud de pago. No se requiere ninguna acción, aunque desde el punto de vista de la lógica de negocio puedes ofrecer un descuento al usuario o recordárselo más adelante. |
| paymentInvalid | 3 | Este error indica que uno de los parámetros de pago no fue reconocido por el App Store. |
| paymentNotAllowed | 4 | Este código de error indica que el usuario no tiene permiso para autorizar pagos. |
| storeProductNotAvailable | 5 | Este código de error indica que el producto solicitado no está disponible en el store. Intenta reinstalar la app. |
| cloudServicePermissionDenied | 6 | Este código de error indica que el usuario no ha permitido el acceso a la información del servicio en la nube. |
| cloudServiceNetworkConnectionFailed | 7 | Este código de error indica que el dispositivo no pudo conectarse a la red. |
| cloudServiceRevoked | 8 | Este código de error indica que el usuario ha revocado el permiso para usar este servicio en la nube. |
| privacyAcknowledgementRequired | 9 | Este código de error indica que el usuario aún no ha aceptado la política de privacidad de Apple. |
| unauthorizedRequestData | 10 | Este código de error indica que la app está intentando usar una propiedad para la que no tiene el entitlement necesario. |
| invalidOfferIdentifier | 11 | El Asegúrate de configurar las ofertas deseadas en App Store Connect y de pasar un identificador de oferta válido. |
| invalidSignature | 12 | Este código de error indica que la firma en un descuento de pago no es válida. |
| missingOfferParams | 13 | Este código de error indica que faltan parámetros en un descuento de pago. |
| invalidOfferPrice | 14 | Este código de error indica que el precio que especificaste en App Store Connect ya no es válido. Las ofertas siempre deben representar un precio con descuento. |
| noProductIDsFound | 1000 | Este error indica que ninguno de los productos que solicitaste en el paywall está disponible para comprar en el App Store, aunque estén listados allí. A veces puede aparecer junto con una advertencia Si encuentras este error, sigue los pasos de la sección Solución para el error Code-1000 |
| productRequestFailed | 1002 | No se pueden obtener los productos disponibles en este momento. |
| cantMakePayments | 1003 | Las compras in-app no están permitidas en este dispositivo. Consulta la guía de solución de problemas. |
| cantReadReceipt | 1005 | No hay ningún recibo válido disponible en el dispositivo. Esto puede ser un problema durante las pruebas en sandbox. En el sandbox no tendrás un archivo de recibo válido hasta que hagas una compra real, así que asegúrate de hacer una antes de acceder a él. Durante las pruebas en sandbox, verifica también que hayas iniciado sesión en el dispositivo con una cuenta sandbox de Apple válida. |
| productPurchaseFailed | 1006 | La compra del producto falló. Esto envuelve un error subyacente de StoreKit; lee originalError (o activa los logs detallados para verlo en la consola) para conocer el motivo real. El error envuelto suele ser uno de los códigos de StoreKit del 0 al 14 de la tabla anterior, siendo los más habituales paymentCancelled, paymentInvalid, paymentNotAllowed o invalidOfferPrice. Si no puedes identificar un motivo concreto, prueba con un nuevo perfil sandbox; si sigue fallando, contacta con el soporte de Apple. |
| refreshReceiptFailed | 1010 | La operación de actualización del recibo falló. |
| fetchSubscriptionStatusFailed | 1020 | No se pudo obtener el estado de la suscripción desde el App Store. |
| unknownTransactionId | 1030 | El identificador de transacción es desconocido. |
| paymentPendingError | 1050 | El pago está pendiente en este momento. |
Errores de red
| Error | Code | Solution |
|---|---|---|
| notActivated | 2002 | El SDK de Adapty no está activado. Se produce con mayor frecuencia cuando una splash screen o un hook de UI temprano llama a métodos de Adapty antes de que Adapty.activate retorne. El síntoma es intermitente y puede no reproducirse en el simulador porque el timing en dispositivo real es diferente. Espera al completion handler o al resultado asíncrono de activate antes de programar cualquier otra llamada al SDK. Consulta Orden de llamadas en el SDK de iOS para ver la secuencia completa. |
| badRequest | 2003 | Solicitud incorrecta. En getPaywall, esto generalmente significa que el placement solicitado no existe en la app a la que pertenece tu API key. Verifica que el ID del placement esté copiado exactamente y que la API key y el placement provengan de la misma app en el Adapty Dashboard. |
| serverError | 2004 | Error del servidor. Vuelve a intentarlo después de un tiempo. Si el problema persiste, contacta al equipo de soporte de Adapty. Este código también cubre el throttling: si llamas al mismo endpoint con demasiada frecuencia (por ejemplo, actualizaciones frecuentes de perfil), el servidor responde con 429 y el SDK bloquea ese endpoint hasta que transcurra el intervalo de reintento. |
| networkFailed | 2005 | El error indica problemas con la conexión de red en el dispositivo del usuario. Prueba desactivando la VPN o cambiando a WiFi desde una red móvil, o viceversa. |
| decodingFailed | 2006 | Este error indica que falló la decodificación de la respuesta: el SDK recibió datos que no puede parsear. Si ocurre mientras el SDK carga un archivo de respaldo local, el archivo es más antiguo de lo que espera el SDK: descarga un archivo actualizado desde la página Placements. Una discrepancia de versión del paywall de respaldo también puede manifestarse como el error 3001. |
| encodingFailed | 2009 | Este error indica que falló la codificación de la solicitud. |
Errores generales
| Error | Code | Solution |
|---|---|---|
| analyticsDisabled | 3000 | No podemos gestionar eventos de analítica porque has desactivado esta opción. |
| wrongParam | 3001 | Este error indica que algunos de tus parámetros no son correctos. Si usas el antiguo Paywall Builder y no puedes mostrar un paywall debido a este error, activa Show on device en ese builder. Otra posible causa es que la versión del archivo de respaldo local no coincida con la versión del SDK. Descarga un nuevo archivo desde el dashboard. |
| activateOnceError | 3005 | No es posible llamar al método .activate más de una vez. |
| profileWasChanged | 3006 | El perfil de usuario cambió durante la operación. Esto ocurre cuando se llama a un método mientras Adapty.identify todavía está en curso — la llamada en vuelo llega a un perfil que está a punto de ser reemplazado y el SDK la rechaza. Siempre usa await con identify (o su completion handler) antes de cualquier llamada de acción del usuario. Consulta Orden de llamadas en el SDK de iOS. |
| unsupportedData | 3007 | Este error indica que el formato de datos no es compatible con el SDK. |
| unidentifiedUserLogout | 3020 | No es posible llamar al método logout para un usuario no identificado. |
| fetchTimeoutError | 3101 | Este error indica que la operación de obtención de datos superó el tiempo de espera. |
| operationInProgress | 3201 | Otra operación del mismo tipo sigue en ejecución. Lo devuelve showStoreMessages cuando una llamada anterior todavía muestra mensajes del App Store. Espera a que finalice y vuelve a intentarlo. |
| resolverFailure | 3202 | El SDK no pudo encontrar el recurso que necesita la operación. Lo devuelve el método showStoreMessages de UIKit cuando no se pasa una window scene y no existe ninguna escena activa en primer plano. Pasa la escena explícitamente o llama al método de nuevo cuando la app esté en primer plano. |
| operationInterrupted | 9000 | El sistema interrumpió esta operación. |
Fetches lentas justo después de updateProfile
Si estableces atributos personalizados con updateProfile y obtienes un placement en la misma sesión, el SDK puede calcular el hash de segmento del placement a partir de atributos que aún no han terminado de propagarse. Reintenta una vez que el hash de segmento se actualiza, por lo que el síntoma es una obtención más lenta en lugar de un error. La obtención falla solo cuando el reintento sigue sin coincidir, lo que significa que la escritura del atributo no se ha completado.
Para evitar el reintento, usa await con updateProfile antes de obtener el placement. Consulta Orden de llamadas en el SDK de iOS.
Otros problemas
Si aún no has encontrado una solución, los siguientes pasos pueden ser:
- Actualizar el SDK a la última versión: Siempre recomendamos actualizar a las últimas versiones del SDK, ya que son más estables e incluyen correcciones para problemas conocidos.
- Contacta con el equipo de soporte u obtén ayuda de otros desarrolladores en el foro de soporte.
- Contacta con el equipo de soporte en support@adapty.io o a través del chat: Si no estás listo para actualizar el SDK o no te ha ayudado, contacta con nuestro equipo de soporte. Ten en cuenta que tu problema se resolverá más rápido si activas el registro detallado y compartes los logs con el equipo. También puedes adjuntar fragmentos de código relevantes.