Error handling and diagnostics
SDK-level known limitations (WebSocket disconnect behavior, hostname verification specifics) are in Known limitations. Step-by-step diagnostics is in Troubleshooting.
Error reference
What each method throws
| Method | Condition | Behavior |
|---|---|---|
authorize() before init() | The SDK is not initialized | IllegalStateException |
getChatFragment() before init() or authorize() | The SDK is not initialized or the user is not authorized | Returns null |
send(message) without authorization | The user is not authorized | Returns false |
handleFCMMessage() before init() | The SDK is not initialized | IllegalStateException* |
init() with an empty providerUid | Empty string | IllegalArgumentException |
authorize() with an empty identifier | Empty ChatUser.identifier | IllegalArgumentException |
* When using initAsync(), the call is deferred until initialization completes (runAfterInit).
Network errors (Error)
The SDK transparently propagates the HTTP error code (or an internal transport code) via ChatCenterUIListener.networkErrorReceived(error: Error). There is no special handling of specific values — the code's meaning is defined by your backend and HTTP standards. Typical values:
error.code | Standard meaning | Recommended integrator action |
|---|---|---|
401 | Unauthorized — the token has expired or is invalid | Re-call authorize() with a fresh token |
403 | Access denied | Check providerUid and queue settings on the edna side |
500+ | Server error | Show a retry to the user, try again later |
Error callbacks via ChatCenterUIListener
networkErrorReceived
Called when network errors occur. The error object has type edna.chatcenter.core.main.Error (not java.lang.Error) and contains:
error.code: Int— numeric code (HTTP code from the server or internal WebSocket transport code)error.message: String— text descriptionerror.stacktrace: Array<out StackTraceElement>?— call stack (nullable)
import edna.chatcenter.core.main.Error // required — otherwise Kotlin resolves to kotlin.Error
override fun networkErrorReceived(error: Error) {
Log.e("ChatCenter", "Network error [${error.code}]: ${error.message}")
error.stacktrace?.forEach { element ->
Log.d("ChatCenter", " at $element")
}
}
exceptionReceived
Called when internal SDK exceptions occur. The trace parameter contains the exception's call stack.
override fun exceptionReceived(trace: String) {
Log.e("ChatCenter", "Internal SDK exception:\n$trace")
}
Logging practices
Enabling logs (ChatLoggerConfig)
val loggerConfig = ChatLoggerConfig(
applicationContext = applicationContext,
logLevel = ChatLogLevel.DEBUG
)
val chatCenterUI = ChatCenterUI(applicationContext, loggerConfig).apply {
init(providerUid = "your_provider_uid", config = chatConfig)
}
ChatLogLevel levels: VERBOSE, DEBUG, INFO, WARNING, ERROR, FLUSH. For production, use ERROR — this reduces I/O from log writes.
Collecting logs
- Logcat — logs are printed with the
ELogtag prefix (e.g.,ELog INFO,ELog ERROR). - File on the device — the SDK also duplicates logs to a file. You can export them via View → Tool Windows → Device Explorer in Android Studio.
- Shake-to-export — with
ChatLoggerConfig.shouldShowSendMenuenabled, shaking the device opens an export screen for the logs.
LogInterceptor for custom analytics
To intercept and process SDK logs, use LogInterceptor. Details and an example implementation are in Advanced settings → Logger.
Edge cases
Calling authorize() before init()
If authorize() is called before init() completes, the SDK throws IllegalStateException. Always call init() in Application.onCreate() and wait for it to complete before calling authorize().
Repeated init()
A repeated init() is allowed but is performed strictly sequentially and is accompanied by a partial SDK state reset. Usually one init() call in Application.onCreate() is enough — a repeated call is only needed when changing ChatConfig (URL/providerUid).
Changing configuration during an active chat
Changing ChatConfig or the theme on the fly while ChatFragment is open is not recommended — open screens will continue to work with the old context. Close the chat, run init(...) with the new configuration, and open the chat again.
SDK behavior without network (offline mode)
Message queue
- On send, the message is saved to local SQLite with status
SENDING - With an active WebSocket, it is sent to the server; the status transitions to
SENT→DELIVERED→READ - On a network error, the status becomes
FAILED; the user can retry from the UI
The full list of MessageStatus values is in the canonical section.
Disconnect behavior
Starting with version 5.21.0, the SDK supports automatic WebSocket reconnect. It is disabled by default and is enabled with WSConfig.isReconnectEnabled = true — see Network config.
When isReconnectEnabled = false, the SDK closes the socket on error and signals via ChatCenterUIListener.networkErrorReceived(). Until authorize(user, auth) is re-called, messages do not go through the WebSocket — they remain in the local DB with status SENDING / FAILED. A repeated authorize() is idempotent and brings the session back up.
In the app:
- Subscribe to
networkErrorReceivedand show an offline indicator. - When the internet is restored (
ConnectivityManager.NetworkCallback), callchatCenterUI.authorize(user, auth)again.
- Keepalive pings: the interval is set by
WSConfig.pingInterval(30 s by default) — this only detects disconnects, it does not trigger reconnect. - When
connectionTimeoutis exceeded, the SDK signals an error viaChatCenterUIListener.networkErrorReceived().
Local storage
A full description of all SDK storages (SQLite, three prefs files, RAM) including encryption and what survives logout() is in Authorization → User data storage.
keepWebSocketActive is a client-side fallbackChatConfig.keepWebSocketActive is applied only if the server did not send a keepSocketActive value in channelSettings. The server setting overrides the client value without an app update. See Known limitations.
Quick navigation by symptom
If you arrived with a specific issue, use the table below as an entry point.
| Symptom | Canonical section |
|---|---|
CalledFromWrongThreadException in a listener callback | Delegates → Callback threads |
send() returns false | Authorization → authorize() — the user is not authorized |
IllegalStateException on send() / authorize() | Error reference → What each method throws — the SDK is not initialized |
IllegalArgumentException: identifier is blank | Authorization → ChatUser model — the identifier contract |
getChatFragment() returned null | Error reference — the SDK is not initialized or the user is not authorized |
The FCM/HCM token is not cleared after logout() | Authorization → Logout — FCM/HCM caution and workaround |
| Message history is gone after the app is killed | Authorization → User data storage — SQLite in-memory, expected behavior |
| Crash on reading prefs after restoring from cloud backup | Advanced settings → App backup settings |
HTTP 401 in networkErrorReceived | Network errors → Typical codes — re-call authorize() with a fresh token |
| WebSocket disconnects with no reconnect | Disconnect behavior — WSConfig.isReconnectEnabled |
For deep diagnostics (logs, dumps, repro steps), see Advanced settings → Troubleshooting.