JavaScript SDK / Errors
Errors
Every error the SDK throws derives from ZeliError, so you can
catch the base type to handle anything, or a specific subclass to react to one
failure mode.
import {
ZeliError,
ZeliErrorCode,
ConfigurationError,
AuthenticationError,
ConnectionError,
TimeoutError,
SessionError,
GatewayUnavailableError,
} from "@zeligate/zeli-avatar";ZeliError
Base class for all SDK errors. Extends Error.
| Member | Type | Description |
|---|---|---|
message | string | Human-readable description. |
name | string | The concrete subclass name. |
code | string | null | Stable, machine-readable code. null where the failure has no code. |
The prototype chain is restored explicitly in the constructor. Extending Error
across a transpiled target loses it otherwise, and instanceof is how every
documented catch arm is written.
The hierarchy
ZeliError
├── ConfigurationError
├── AuthenticationError
├── ConnectionError
│ ├── TimeoutError
│ └── GatewayUnavailableError
└── SessionError| Error | Thrown when | code |
|---|---|---|
ConfigurationError | The client or avatar configuration is invalid or incomplete: a missing or malformed serverUrl, a persona field no box reads, an unresolvable video element, or a box answering a shape the SDK does not understand. | null |
AuthenticationError | The API key or session token was rejected by the box. | unauthorized |
ConnectionError | The transport, HTTP signalling or WebRTC, failed to establish or dropped. | null |
TimeoutError | An operation did not complete in time, including waitUntilAvatarReady. | timeout |
SessionError | The box refused to start a session, an active session failed, or a gateway-gated call was made without the gateway. Also covers sending on an ended or interrupted talk stream, and empty message text. | null |
GatewayUnavailableError | The box does not expose the SDK control gateway (/api/session/ws). | gateway_unavailable |
ZeliErrorCode
enum ZeliErrorCode {
UNAUTHORIZED = "unauthorized",
TIMEOUT = "timeout",
GATEWAY_UNAVAILABLE = "gateway_unavailable",
}Every timeout the SDK can hit is a transport that never came up, so a
documented catch (e) { if (e instanceof ConnectionError) ... }
keeps catching them. Narrowing to TimeoutError is the addition,
not a replacement. GatewayUnavailableError sits under the same
parent for the same reason.
Catching
Order the arms from narrow to broad, since the narrow ones are subclasses:
import {
ZeliError,
AuthenticationError,
GatewayUnavailableError,
TimeoutError,
ConnectionError,
} from "@zeligate/zeli-avatar";
try {
const { session } = await client.streamToVideoElement("stage");
await session.talk("Hello.");
} catch (error) {
if (error instanceof AuthenticationError) {
await refreshSessionToken(); // the token expired, mint another
} else if (error instanceof GatewayUnavailableError) {
await session.sendUserMessage("Hello."); // no gateway, use the HTTP path
} else if (error instanceof TimeoutError) {
retryLater();
} else if (error instanceof ConnectionError) {
reportNetworkTrouble();
} else if (error instanceof ZeliError) {
console.error(error.name, error.code, error.message);
} else {
throw error; // not ours
}
}Reacting on code instead, when the error crosses a boundary that flattens the
class:
import { ZeliError, ZeliErrorCode } from "@zeligate/zeli-avatar";
if (error instanceof ZeliError && error.code === ZeliErrorCode.UNAUTHORIZED) {
await refreshSessionToken();
}Errors that are not thrown
Two things a developer expects to be errors are reported instead, because they are states rather than failures:
| Situation | How you learn about it |
|---|---|
| The browser blocked unmuted autoplay | muted: true on the attach result. See Media. |
| The box streamed a stand-in face, or a tone this avatar never advertised | ZeliEvent.SERVER_WARNING, and session.substitutedAvatar. |
It is the only channel for both of those. Without a handler, the symptom is the wrong face on screen and no explanation anywhere.