---
title: "What does Play Billing SERVICE_TIMEOUT (-3) mean?"
description: "SERVICE_TIMEOUT (-3) means Google Play did not answer before the request timed out. Only Billing Library 5.2.0 and earlier return it; retry the same call, with backoff in the background."
url: https://revenuedot.app/docs/errors/play-billing-service-timeout
---

# What does Play Billing SERVICE_TIMEOUT (-3) mean?

Play Billing SERVICE_TIMEOUT (-3) means a request reached its maximum timeout before Google Play could answer.

## Quick facts

| | |
|---|---|
| Error | `BillingClient.BillingResponseCode.SERVICE_TIMEOUT` (-3) |
| Where | Google Play Billing Library (`BillingResult.responseCode`) |
| What the vendor says | The request has reached the maximum timeout before Google Play responds. |

## Cause

- Google gives an example: a delay in executing the action that the Billing Library call asked for.
- Only Billing Library 5.2.0 and earlier return it. From 6.0.0 `SERVICE_UNAVAILABLE` is returned for the same problem and `SERVICE_TIMEOUT` is deprecated.
- Unlike `SERVICE_DISCONNECTED`, the connection to the billing service is still up.

## Fix

1. Retry the same Billing Library call. Use a simple retry for something the person waits on, and exponential backoff for background work.
2. Do not call `startConnection()` again, because the connection is not severed.
3. Upgrade the Billing Library. Version 8 is required for new apps and updates from 2026-08-31, and it never returns this code.
4. Treat `SERVICE_UNAVAILABLE` the same way, so one handler covers both.

## Example

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

// Retry the same call on a timeout; the connection is fine (Google's guidance for code -3).
suspend fun <T> retryOnTimeout(maxTries: Int = 3, call: suspend () -> Pair<BillingResult, T>): Pair<BillingResult, T> {
    var result = call()
    var tries = 1
    while (result.first.responseCode == BillingClient.BillingResponseCode.SERVICE_TIMEOUT && tries < maxTries) {
        delay(2_000L * tries)
        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_TIMEOUT` to `PurchasesErrorCode.StoreProblemError` (code 2) and, inside its own billing code, treats it as `ServiceUnavailable`. See [what storeProblemError means](https://revenuedot.app/docs/errors/sdk-store-problem-error.md).

## Related

- [What does Play Billing SERVICE_UNAVAILABLE (2) mean?](https://revenuedot.app/docs/errors/play-billing-service-unavailable.md)
- [What does Play Billing SERVICE_DISCONNECTED (-1) mean?](https://revenuedot.app/docs/errors/play-billing-service-disconnected.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_TIMEOUT](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)
- [RevenueDot purchases-android: google/BillingResponse.kt](https://github.com/revenuedot/purchases-android/blob/revenuedot/main-patches/purchases/src/main/kotlin/com/revenuecat/purchases/google/BillingResponse.kt)

Checked: 2026-10-03
