> ## Documentation Index
> Fetch the complete documentation index at: https://chatbase.co/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Exception hierarchy and error handling patterns for the Chatbase Android SDK.

## Exception Hierarchy

All SDK errors extend `ChatbaseException`:

```
ChatbaseException
├── ApiException        — API errors from the Chatbase server
└── NetworkException    — Connection failures, DNS errors, timeouts
```

## ApiException

`class ApiException : ChatbaseException` — **Package:** `com.chatbase.sdk.exception`

Thrown when the Chatbase API returns an error response.

```kotlin theme={null}
class ApiException(
    val httpStatus: Int,
    val errorCode: String,
    val errorMessage: String,
    val details: Map<String, String>? = null
) : ChatbaseException
```

**httpStatus** `Int` *required*

The HTTP status code of the error response (e.g. `401`, `403`, `429`).

**errorCode** `String` *required*

Machine-readable error code. Use this for programmatic handling.

**errorMessage** `String` *required*

Human-readable error description.

**details** `Map\<String, String\>?`

Optional field-level validation errors.

### Convenience Properties

```kotlin theme={null}
val isRateLimited: Boolean      // httpStatus == 429
val isNotFound: Boolean         // httpStatus == 404
val isCreditsExhausted: Boolean // httpStatus == 402
```

> [!TIP]
>
> For statuses without a helper — such as `401` (authentication) or `403` (access denied) — check `httpStatus` or `errorCode` directly.

## Error Codes

These are the error codes you may encounter through `ApiException.errorCode`:

<table>
  <thead>
    <tr>
      <th>Status</th>
      <th>Code</th>
      <th>Description</th>
    </tr>
  </thead>

  <tbody>
    <tr><td>400</td><td>`VALIDATION_INVALID_BODY`</td><td>The request body failed validation. `details` maps field names to messages. Also returned when a tool result exceeds the 20 KB limit.</td></tr>
    <tr><td>400</td><td>`CHAT_RETRY_NO_USER_MESSAGE`</td><td>The message passed to `retry()` has no preceding user message to retry from.</td></tr>
    <tr><td>401</td><td>`AUTH_INVALID_JWT`</td><td>The JWT token passed to `identify()` is invalid, expired, or could not be verified — including when identity verification is not configured for the AI agent. See [User Identity](https://chatbase.co/docs/android-sdk/user-identity.md).</td></tr>
    <tr><td>402</td><td>`CHAT_CREDITS_EXHAUSTED`</td><td>The workspace's message credit balance is zero. Upgrade the plan or wait for credits to reset. Caught by `isCreditsExhausted`.</td></tr>
    <tr><td>402</td><td>`CHAT_AGENT_CREDITS_EXHAUSTED`</td><td>The specific AI agent's credit allocation has been used up. Caught by `isCreditsExhausted`.</td></tr>
    <tr><td>403</td><td>`AUTH_OWNERSHIP_MISMATCH`</td><td>The conversation belongs to a different user or device. Also returned by `retry()` and `listMessages()` when the conversation does not exist.</td></tr>
    <tr><td>403</td><td>`CHAT_CONVERSATION_MISMATCH`</td><td>The conversation could not be resolved for this AI agent.</td></tr>
    <tr><td>403</td><td>`CHAT_MODEL_NOT_ALLOWED`</td><td>The AI agent uses a model not available on the current plan.</td></tr>
    <tr><td>403</td><td>`CHAT_CONVERSATION_NOT_ONGOING`</td><td>The conversation has ended or was taken over and cannot receive new messages. Start a new conversation.</td></tr>
    <tr><td>404</td><td>`AGENT_NOT_FOUND`</td><td>No AI agent matches the provided ID, or the **Android SDK channel is not enabled** for the AI agent (see [Quick Start](https://chatbase.co/docs/android-sdk/quickstart.md#quick-start)). Caught by `isNotFound`.</td></tr>
    <tr><td>404</td><td>`RESOURCE_NOT_FOUND`</td><td>The conversation or message does not exist. Caught by `isNotFound`.</td></tr>
    <tr><td>404</td><td>`CHAT_RETRY_MESSAGE_NOT_FOUND`</td><td>The message ID provided for `retry()` was not found. Caught by `isNotFound`.</td></tr>
    <tr><td>404</td><td>`RESOURCE_TOOL_CALL_NOT_FOUND`</td><td>The tool call was not found or has expired. Can surface through the automatic tool loop. Caught by `isNotFound`.</td></tr>
    <tr><td>404</td><td>`RESOURCE_TOOL_CALL_MISMATCH`</td><td>The tool call does not belong to this conversation. Caught by `isNotFound`.</td></tr>
    <tr><td>404</td><td>`RESOURCE_TOOL_RESULT_NOT_PENDING`</td><td>No pending tool result exists for this tool call — usually a duplicate submission. Caught by `isNotFound`.</td></tr>
    <tr><td>429</td><td>`RATE_LIMIT_TOO_MANY_REQUESTS`</td><td>Rate limit exceeded (1,000 requests per 10 seconds per device). Back off and retry. Caught by `isRateLimited`.</td></tr>
    <tr><td>500</td><td>`CHAT_STREAMING_ERROR`</td><td>The response stream failed server-side. Safe to retry.</td></tr>
    <tr><td>500</td><td>`INTERNAL_SERVER_ERROR`</td><td>An unexpected server error occurred. Retry, or contact support if it persists.</td></tr>
  </tbody>
</table>

## NetworkException

`class NetworkException : ChatbaseException` — **Package:** `com.chatbase.sdk.exception`

```kotlin theme={null}
class NetworkException(
    message: String,
    cause: Throwable? = null
) : ChatbaseException
```

Thrown for connection-level failures — DNS errors, socket timeouts, no internet connectivity, and similar issues.

## Handling Errors

> [tab] Suspend Functions
>
> Use a try-catch block with the SDK's exception hierarchy:
>
> ```kotlin theme={null}
> try {
>     val response = client.sendMessage("Hello")
> } catch (e: ApiException) {
>     when {
>         e.httpStatus == 401 -> {
>             println("Authentication failed. Check your JWT token.")
>         }
>         e.httpStatus == 403 -> {
>             println("Access denied. Check conversation ownership or plan.")
>         }
>         e.isRateLimited -> {
>             println("Rate limited. Back off and retry.")
>         }
>         e.isCreditsExhausted -> {
>             println("No credits remaining. Upgrade plan.")
>         }
>         e.isNotFound -> {
>             println("Not found. Check your agent ID.")
>         }
>         else -> {
>             println("API error: ${e.errorCode} — ${e.errorMessage}")
>         }
>     }
> } catch (e: NetworkException) {
>     println("Network error: ${e.message}")
> } catch (e: ChatbaseException) {
>     println("Unknown SDK error: ${e.message}")
> }
> ```

> [tab] Streaming Callbacks
>
> Handle errors via the `onError` callback:
>
> ```kotlin theme={null}
> client.sendMessage("Hello") {
>     onTextDelta { delta -> print(delta) }
>     onError { error ->
>         when (error) {
>             is ApiException -> println("API error: ${error.errorCode}")
>             is NetworkException -> println("Network error: ${error.message}")
>             else -> println("Error: ${error.message}")
>         }
>     }
> }
> ```

> [tab] Flow
>
> Check for `ChatStreamEvent.Error` events:
>
> ```kotlin theme={null}
> client.sendMessageStream("Hello").collect { event ->
>     when (event) {
>         is ChatStreamEvent.TextDelta -> print(event.delta)
>         is ChatStreamEvent.Error -> {
>             when (val ex = event.exception) {
>                 is ApiException -> println("${ex.errorCode}: ${ex.errorMessage}")
>                 is NetworkException -> println("Network: ${ex.message}")
>                 else -> println("Error: ${ex.message}")
>             }
>         }
>         else -> {}
>     }
> }
> ```

## Related

> [card] [Streaming](https://chatbase.co/docs/android-sdk/streaming.md)
>
> Streaming callbacks and error events

> [card] [Overview](https://chatbase.co/docs/android-sdk/overview.md)
>
> SDK setup and configuration


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.