SDK error · code 37

signatureVerificationFailed (error code 37): Signature verification failed

What it means

signatureVerificationFailed (code 37 on iOS, 36 on Android) means a response did not pass the SDK's signature check. The SDK raises it only when verification is enforced. In the usual informational mode it logs the failure and marks customer info FAILED but still works. The stock SDK checks RevenueCat's key, which RevenueDot cannot sign with, so turn verification off.

Code

37

iOS (Swift)

ErrorCode.signatureVerificationFailed

Android (Kotlin)

PurchasesErrorCode.SignatureVerificationError

Causes

Why the SDK returns signatureVerificationFailed

  • iOS: a response failed verification while the SDK was in enforced mode. In any other mode it logs the failure and forwards the response (HTTPClient.swift). In the SDK source, enforced mode is marked unavailable for now (Configuration.swift).
  • Android: a SignatureVerificationException becomes SignatureVerificationError (errors.kt). Android numbers it 36, while iOS uses 37.
  • A server that does not sign with the key the SDK trusts. The stock SDK trusts only RevenueCat's key.
  • A response changed in transit, or a proxy that rewrites it. RevenueCat describes verification as detecting tampered requests (RevenueCat docs).

Fix

How to fix signatureVerificationFailed

  1. 01

    Turn verification off

    Set the entitlement verification mode to disabled in the SDK configuration. Native iOS and Android default to informational, so they log a failure against RevenueDot until you do.

  2. 02

    Never use enforced mode with the stock SDK

    It would reject every RevenueDot response. Use the stock SDK in disabled mode.

  3. 03

    Or build the forks with your key

    To get VERIFIED, give the server a signing key and build the SDK forks with its public key. See signature verification failed in proxy mode.

  4. 04

    Check the public key

    GET /.well-known/revenuedot-signing-key on your server returns the public key it signs with. Compare it with the key in your SDK build.

In your app

How to handle it in code

  • In informational mode nothing is thrown, and access is still granted by the entitlements in the response. Log the failure and move on.
  • If you build forks with enforcement, do not retry in a loop. Treat repeated failures as a tamper signal or a key mismatch.
  • Do not grant access from a response that failed verification when you have turned enforcement on.
Match the errorSwift · Kotlin
// Swift
do {
  let result = try await Purchases.shared.purchase(package: package)
} catch let error as ErrorCode where error == .signatureVerificationFailed {
  // handle signature verification failed
}

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

On RevenueDot: RevenueDot signs every 2xx and 3xx response under /v1 and /rcbilling when REVENUEDOT_SIGNING_KEY is set, with Ed25519, and serves the public key at /.well-known/revenuedot-signing-key. The stock SDK cannot trust that key, so it reads every RevenueDot response as FAILED until you disable verification or use a fork built with the key. See Trusted Entitlements.

FAQ

signatureVerificationFailed: questions people ask

Why does the SDK say verification FAILED against RevenueDot?

The stock SDK trusts only RevenueCat's signing key, and RevenueDot cannot sign with it. In informational mode access still works. Set the verification mode to disabled to silence it.

Why is signatureVerificationFailed code 36 on Android?

The Android enum numbers SignatureVerificationError 36, while iOS and the hybrid enums use 37. Match by name.

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

The React Native PURCHASES_ERROR_CODE enum in the SDK source has no member for it, so compare error.code with the string "37". In Flutter, convert the PlatformException with PurchasesErrorHelper.getErrorCode(e) and compare the result with PurchasesErrorCode.signatureVerificationFailed. On iOS the readable name in userInfo is SIGNATURE_VERIFICATION_FAILED.

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