Guides / Error handling
Error handling
Every error the SDK raises derives from ZeliError, so you can catch
the base type broadly or a specific subclass narrowly.
The hierarchy
ZeliError
├── ConfigurationError # invalid/incomplete client or avatar config
├── AuthenticationError # the server rejected the key / session token
├── ConnectionError # transport (HTTP signalling / WebRTC) failed or dropped
├── SessionError # the server refused a session, or an operation failed
└── TimeoutError # an operation didn't complete in timeEach carries a human-readable message and an optional machine-readable code.
See the Errors reference for the full table.
Catching errors
from zeli import ZeliError, ConnectionError, SessionError, AuthenticationError
try:
async with client.connect() as session:
await session.send_message("Hello")
await session.wait_until_closed()
except AuthenticationError:
... # bad key / session token — see /authentication/
except ConnectionError:
... # couldn't reach the server, or WebRTC failed to establish
except SessionError:
... # server refused the session or an operation failed
except ZeliError as e:
print(f"[{e.code}] {e.message}")Runtime errors via events
Errors that surface after a session is live (server-side failures, or an
exception inside one of your own handlers) are delivered as
ERROR events rather than raised:
from zeli import ZeliEvent
@client.on(ZeliEvent.ERROR)
def on_error(err):
log.warning("zeli error: %s", err)A handler that raises is caught and re-emitted as an ERROR event —
one buggy listener can't take down the session. Keep an ERROR
handler registered so those don't get lost.
Timeouts
ClientOptions.connect_timeout bounds how long the SDK waits for the WebRTC
connection and the control handshake. On expiry it raises ConnectionError (code
"timeout").
from zeli import ClientOptions
options = ClientOptions(server_url="http://your-server:8080", connect_timeout=15.0)