Skip to main content
Version: 5.21.0

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

MethodConditionBehavior
authorize() before init()The SDK is not initializedIllegalStateException
getChatFragment() before init() or authorize()The SDK is not initialized or the user is not authorizedReturns null
send(message) without authorizationThe user is not authorizedReturns false
handleFCMMessage() before init()The SDK is not initializedIllegalStateException*
init() with an empty providerUidEmpty stringIllegalArgumentException
authorize() with an empty identifierEmpty ChatUser.identifierIllegalArgumentException

* 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.codeStandard meaningRecommended integrator action
401Unauthorized — the token has expired or is invalidRe-call authorize() with a fresh token
403Access deniedCheck providerUid and queue settings on the edna side
500+Server errorShow 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 description
  • error.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 ELog tag 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.shouldShowSendMenu enabled, 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()

danger

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 SENTDELIVEREDREAD
  • 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 automatic reconnect is disabled

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 networkErrorReceived and show an offline indicator.
  • When the internet is restored (ConnectivityManager.NetworkCallback), call chatCenterUI.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 connectionTimeout is exceeded, the SDK signals an error via ChatCenterUIListener.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 fallback

ChatConfig.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.

SymptomCanonical section
CalledFromWrongThreadException in a listener callbackDelegates → Callback threads
send() returns falseAuthorization → authorize() — the user is not authorized
IllegalStateException on send() / authorize()Error reference → What each method throws — the SDK is not initialized
IllegalArgumentException: identifier is blankAuthorization → ChatUser model — the identifier contract
getChatFragment() returned nullError 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 killedAuthorization → User data storage — SQLite in-memory, expected behavior
Crash on reading prefs after restoring from cloud backupAdvanced settings → App backup settings
HTTP 401 in networkErrorReceivedNetwork errors → Typical codes — re-call authorize() with a fresh token
WebSocket disconnects with no reconnectDisconnect behaviorWSConfig.isReconnectEnabled

For deep diagnostics (logs, dumps, repro steps), see Advanced settings → Troubleshooting.