---
title: "What does Play Billing SERVICE_UNAVAILABLE (2) mean?"
description: "SERVICE_UNAVAILABLE (2) means the Google Play billing service is unavailable right now. It is transient: retry the same call, with backoff in the background."
url: https://revenuedot.app/docs/errors/play-billing-service-unavailable
---

# What does Play Billing SERVICE_UNAVAILABLE (2) mean?

Play Billing SERVICE_UNAVAILABLE (2) means the Google Play billing service is temporarily unavailable.

## Quick facts

| | |
|---|---|
| Error | `BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE` (2) |
| Where | Google Play Billing Library (`BillingResult.responseCode`) |
| What the vendor says | The service is currently unavailable. |

## Cause

- Google says the billing service is currently unavailable; in most cases a network problem between the device and Google Play billing is behind it.
- From Billing Library 6.0.0 the code is no longer returned for network issues. Those now return `NETWORK_ERROR`, and `SERVICE_UNAVAILABLE` also replaces the deprecated `SERVICE_TIMEOUT`.
- Unlike `SERVICE_DISCONNECTED`, the connection is still up, so only the operation needs a retry.

## Fix

1. Retry the same call. For something the person is waiting on, use a simple retry with a maximum number of attempts.
2. For background work such as acknowledging a purchase, retry with exponential backoff.
3. Do not call `startConnection()` again; the connection is not severed.
4. Keep the number of retries small while the person waits, and then show a message with a Try again button.

## Example

```kotlin
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingResult
import kotlinx.coroutines.delay

// Retry the same call: the connection is fine, the service was briefly unavailable (Google's guidance for code 2).
suspend fun <T> retryOnUnavailable(maxTries: Int = 3, call: suspend () -> Pair<BillingResult, T>): Pair<BillingResult, T> {
    var delayMs = 2_000L
    var result = call()
    var tries = 1
    while (result.first.responseCode == BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE && tries < maxTries) {
        delay(delayMs)
        delayMs *= 2 // exponential backoff, for work the person is not waiting on
        result = call()
        tries++
    }
    return result
}
```

*Not compiled: this Kotlin snippet was not built here because the docs repo has no Kotlin or Android toolchain. Check it against your Play Billing Library or SDK version before you ship it.*

## How the RevenueDot SDK reports it

The RevenueDot `purchases-android` fork maps `SERVICE_UNAVAILABLE` to `PurchasesErrorCode.StoreProblemError` (code 2). Retrying once is reasonable. See [what storeProblemError means](https://revenuedot.app/docs/errors/sdk-store-problem-error.md).

## Related

- [What does Play Billing SERVICE_DISCONNECTED (-1) mean?](https://revenuedot.app/docs/errors/play-billing-service-disconnected.md)
- [What does Play Billing NETWORK_ERROR (12) mean?](https://revenuedot.app/docs/errors/play-billing-network-error.md)
- [What does storeProblemError (code 2) mean in the purchases SDK?](https://revenuedot.app/docs/errors/sdk-store-problem-error.md)

## Source

- [Google: BillingResponseCode.SERVICE_UNAVAILABLE](https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode)
- [Google: Handle BillingResult response codes](https://developer.android.com/google/play/billing/errors)
- [RevenueDot purchases-android: google/errors.kt (how the SDK maps response codes)](https://github.com/revenuedot/purchases-android/blob/revenuedot/main-patches/purchases/src/main/kotlin/com/revenuecat/purchases/google/errors.kt)

Checked: 2026-10-03
