Errors
SpekoClientError and its error codes.
The client SDK throws a single error class, SpekoClientError, tagged with a stable string code.
import { SpekoClientError } from '@spekoai/client';
import type { SpekoClientErrorCode } from '@spekoai/client';Shape
class SpekoClientError extends Error {
code: SpekoClientErrorCode;
cause?: unknown; // original error when wrapping transport failures
}Codes
| Code | Where it's thrown |
|---|---|
CONNECTION_FAILED | VoiceConversation.create() — transport connection rejected. cause is the original transport error. |
MICROPHONE_FAILED | create() — mic acquisition or publishTrack() failed. The room is disconnected before this is thrown. |
NOT_CONNECTED | sendUserMessage / sendContextualUpdate / internal publish() called while status isn't connected. |
INVALID_MESSAGE | No longer raised. Malformed inbound data packets are silently ignored (rooms carry non-protocol data from other publishers). Kept in the type for compatibility. |
DISCONNECTED | Reserved for future use. |
Fatal vs non-fatal
- Fatal errors (connection and microphone failures during
create()) are thrown from thecreate()promise so callers can branch at construction time. - Non-fatal errors (media device errors from the transport) are routed to
onError. The session continues. - Non-protocol data packets (malformed JSON, unknown shapes from other publishers in the room) are silently ignored — they never reach
onError.
Example
try {
const conv = await VoiceConversation.create({ ... });
} catch (err) {
if (err instanceof SpekoClientError) {
switch (err.code) {
case 'CONNECTION_FAILED':
// Token expired, network issue, or transport outage — ask user to retry.
break;
case 'MICROPHONE_FAILED':
// Permission denied or device in use — surface a permissions prompt.
break;
}
}
throw err;
}