# Debugging

### Debug Message Sending

To debug various flows inside the SDK, you can pass your own `ChatClientDebugger` implementation:

<tabs>

<tabs-item value="kotlin" label="Kotlin">

```kotlin
val client = ChatClient.Builder("apiKey", context)
    .clientDebugger(CustomChatClientDebugger())
    .build()
```

</tabs-item>

<tabs-item value="java" label="Java">

```java
ChatClient client = new ChatClient.Builder("apiKey", context)
    .clientDebugger(new CustomChatClientDebugger())
    .build()
```

</tabs-item>

</tabs>

<admonition type="note">

`ChatClientDebugger` can be useful for investigating issues on the user's side.

</admonition>

For example, to debug a message sending flow you can override `ChatClientDebugger.debugSendMessage` function and provide your own `SendMessageDebugger` implementation:

<tabs>

<tabs-item value="kotlin" label="Kotlin">

```kotlin
import io.getstream.result.Error

class CustomChatClientDebugger : ChatClientDebugger {

    override fun onNonFatalErrorOccurred(
        tag: String,
        src: String,
        desc: String,
        error: Error,
    ) {
        // TODO: Implement your custom logic here
    }

    override fun debugSendMessage(
        channelType: String,
        channelId: String,
        message: Message,
        isRetrying: Boolean,
    ): SendMessageDebugger {
        return CustomSendMessageDebugger(
            channelType,
            channelId,
            message,
            isRetrying
        )
    }
}
```

</tabs-item>

<tabs-item value="java" label="Java">

```java
import io.getstream.result.Error;

class CustomChatClientDebugger implements ChatClientDebugger {

    @Override
    public void onNonFatalErrorOccurred(
            @NonNull String tag,
            @NonNull String src,
            @NonNull String desc,
            @NonNull Error error
    ) {
        // TODO: Implement your custom logic here
    }

    @Override
    public SendMessageDebugger debugSendMessage(
        @NonNull String channelType,
        @NonNull String channelId,
        @NonNull Message message,
        boolean isRetrying
    ) {
        return new CustomSendMessageDebugger(
            channelType,
            channelId,
            message,
            isRetrying
        );
    }
}
```

</tabs-item>

</tabs>

Then in your custom `SendMessageDebugger` implementation you can handle the entire message sending flow:

<tabs>

<tabs-item value="kotlin" label="Kotlin">

```kotlin
class CustomSendMessageDebugger(
    private val channelType: String,
    private val channelId: String,
    private val message: Message,
    private val isRetrying: Boolean,
) : SendMessageDebugger {

    override fun onStart(message: Message) {
        // Called when the message sending flow starts.
    }

    override fun onInterceptionStart(message: Message) {
        // Called when the message interception before sending it to the API starts.
        // Reasons for interception might be:
        //   - message attachment uploading
        //   - message enriching by all required information
    }

    override fun onInterceptionUpdate(message: Message) {
        // Called when there are intermediate message data updates.
    }

    override fun onInterceptionStop(result: Result<Message>, message: Message) {
        // Called when the message interception before sending it to the API stops.
    }

    override fun onSendStart(message: Message) {
        // Called when the message sending to the API starts.
    }

    override fun onSendStop(result: Result<Message>, message: Message) {
        // Called when the message sending to the API stops.
    }

    override fun onStop(result: Result<Message>, message: Message) {
        // Called when the message sending flow stops.
    }
}
```

</tabs-item>

<tabs-item value="java" label="Java">

```java
public class CustomSendMessageDebugger implements SendMessageDebugger {
    @NonNull
    private final String channelType;
    @NonNull
    private final String channelId;
    @NonNull
    private final Message message;
    @NonNull
    private final boolean isRetrying;

    public CustomSendMessageDebugger(
            @NonNull String channelType,
            @NonNull String channelId,
            @NonNull Message message,
            boolean isRetrying
    ) {
        this.channelType = channelType;
        this.channelId = channelId;
        this.message = message;
        this.isRetrying = isRetrying;
    }

    @Override
    public void onStart(@NonNull Message message) {
        // Called when the message sending flow starts.
    }

    @Override
    public void onInterceptionStart(@NonNull Message message) {
        // Called when the message interception before sending it to the API starts.
        // Reasons for interception might be:
        //   - message attachment uploading
        //   - message enriching by all required information
    }

    @Override
    public void onInterceptionUpdate(@NonNull Message message) {
        // Called when there are intermediate message data updates.
    }

    @Override
    public void onInterceptionStop(@NonNull Result<Message> result, @NonNull Message message) {
        // Called when the message interception before sending it to the API stops.
    }

    @Override
    public void onSendStart(@NonNull Message message) {
        // Called when the message sending to the API starts.
    }

    @Override
    public void onSendStop(@NonNull Result<Message> result, @NonNull Message message) {
        // Called when the message sending to the API stops.
    }

    @Override
    public void onStop(@NonNull Result<Message> result, @NonNull Message message) {
        // Called when the message sending flow stops.
    }
}
```

</tabs-item>

</tabs>

## Debug Requests

The SDK includes a tool to debug requests and help the user to understand how and when the backend is being requested.

### ApiRequestsAnalyser

The `ApiRequestsAnalyser` can be called at any time to print out all the requests that were made with their information.

Enable it using:

```kotlin
ChatClient.Builder(apiKey, context)
    .debugRequests(true)
    .build()
```

Then you can retrieve the request information using `ApiRequestsAnalyser.dumpRequestByName` or `ApiRequestsAnalyser.dumpAll`.

To clear the analyser data, use `ApiRequestsAnalyser.clearRequestContaining` or `ApiRequestsAnalyser.clearAll`.


---

This page was last updated at 2026-04-17T17:33:32.038Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/android/v6/basics/debugging/](https://getstream.io/chat/docs/sdk/android/v6/basics/debugging/).