SDK error · code 12

unexpectedBackendResponseError (error code 12): Unexpected backend response

What it means

unexpectedBackendResponseError (code 12) means the SDK received a response it could not use: malformed JSON, a missing field, a non-JSON page from a proxy, or on Android a backend error such as 7110 or 7226. Fetch the same path with curl and compare. Check any proxy between the app and the server, and never grant access from the error.

Code

12

iOS (Swift)

ErrorCode.unexpectedBackendResponseError

Android (Kotlin)

PurchasesErrorCode.UnexpectedBackendResponseError

Causes

Why the SDK returns unexpectedBackendResponseError

  • iOS: the response could not be decoded, or it was not an HTTP response at all (NetworkError.swift).
  • iOS: a response to a promotional offer signing request, or an offerings request, that lacked the fields the SDK needs.
  • Android: the backend answered 7104, 7110 (internal server error), 7226 (bad request) or 7234 (invalid Apple subscription key), which the Android mapping sends here (errors.kt). Android also raises it for offerings it cannot parse.
  • A proxy, firewall, captive portal or CDN between the app and the server returned an HTML page instead of JSON.
  • A server and an SDK whose response formats do not match, for example an old server with a new SDK.
Backend codeMeaning
7104Invalid App Store shared secret. Android maps it to unexpectedBackendResponseError; iOS maps it to invalidCredentialsError.
7110Internal server error. Android maps it here; iOS maps it to unknownBackendError.
7226Bad request. Android maps it here; iOS maps it to unknownBackendError.
7234Invalid Apple subscription key. Android maps it here; iOS maps it to invalidAppleSubscriptionKeyError.

Fix

How to fix unexpectedBackendResponseError

  1. 01

    Fetch the same request by hand

    Call the path from the log with curl and the same key. If the answer is not the JSON the SDK expects, the problem is on the server side or in between.

  2. 02

    Look for an intermediary

    A captive portal, a corporate proxy or a CDN rule that rewrites errors into HTML breaks decoding. Test on another network.

  3. 03

    Read the extra context

    On iOS, userInfo carries extra_context and the response description. They show what the SDK saw.

  4. 04

    Update server and SDK together

    Run a current server build and a current SDK, so the response shapes match.

In your app

How to handle it in code

  • A limited retry is fine, because a proxy hiccup can pass. Do not loop.
  • Show a generic "something went wrong" message and log the request path and the response.
  • Do not grant access from the error.
Match the errorSwift · Kotlin
// Swift
do {
  let result = try await Purchases.shared.purchase(package: package)
} catch let error as ErrorCode where error == .unexpectedBackendResponseError {
  // handle unexpected backend response
}

// Kotlin
if (error.code == PurchasesErrorCode.UnexpectedBackendResponseError) { /* ... */ }

On RevenueDot: RevenueDot answers every error with a JSON body and application/json, because iOS ignores bodies otherwise and Android fails on empty ones. Its own unexpected failures are HTTP 500 with code 7110, which the Android SDK shows as this error and the iOS SDK shows as unknownBackendError.

FAQ

unexpectedBackendResponseError: questions people ask

What does "Received malformed response from the backend" mean?

The SDK could not decode what the server sent: invalid JSON, a missing field, or a page that is not JSON. Fetch the same path with curl and check for a proxy that rewrites responses.

Why does Android show unexpectedBackendResponseError for a 500?

The Android mapping sends backend codes 7110 (internal server error), 7226 (bad request), 7104 and 7234 to this error. The iOS SDK reports 7110 and 7226 as unknownBackendError.

How do I check for unexpectedBackendResponseError in React Native and Flutter?

In React Native, compare error.code with PURCHASES_ERROR_CODE.UNEXPECTED_BACKEND_RESPONSE_ERROR. In Flutter, convert the PlatformException with PurchasesErrorHelper.getErrorCode(e) and compare the result with PurchasesErrorCode.unexpectedBackendResponseError.

Get started

Keep the RevenueCat SDK. Change the backend.

RevenueDot answers the same SDK calls with the same error codes. Start free on RevenueDot Cloud, free up to $10,000 a month in tracked revenue.

Already have an account? Sign in · Prefer your own servers? Self-host free