Appearance
Errors
Errors reach your page as the error event: { code, message, recoverable, docs }, where docs links to the code's section below. When widget.js can't load a chat, it also prints the error in the browser console with a link here.
js
WirefaceChat.on('error', e => {
if (!e.recoverable) myMonitoring.report(e.code, e.message);
});Errors the visitor can deal with in the chat (a "slow down" notice, for example) show in the chat window and are not emitted. Server codes travel over the widget's WebSocket in an error message (see the protocol); widget codes come from widget.js or the chat window.
| Code | Kind | From |
|---|---|---|
origin_not_allowed | server | Server: the config request (HTTP 403) and the WebSocket (fatal, closes with 4403). |
bot_unavailable | server | Server: the WebSocket (fatal, closes with 4404). |
identity_required | server | Server: the WebSocket (fatal, closes with 4403). |
identity_invalid | server | Server: the WebSocket. Fatal in required mode (closes with 4403); otherwise the chat carries on anonymously. |
rate_limited | server | Server: the WebSocket (too many connections from one IP: fatal, closes with 4429; the other limits: not fatal) and the upload endpoint (HTTP 429). |
spend_cap_reached | server | Server: the WebSocket, when voice starts (not fatal). |
voice_capacity | server | Server: the WebSocket, when voice starts (not fatal). |
voice_unavailable | server | Server: the WebSocket (not fatal). |
session_limit | server | Server: the WebSocket (not fatal). |
provider_unavailable | server | Reserved: not sent to widgets in this version. |
provider_error | server | Reserved: not sent to widgets in this version. |
unsupported | server | Server: the WebSocket (not fatal). |
protocol_unsupported | server | Server: the WebSocket (fatal, closes with 4400). |
bad_message | server | Server: the WebSocket (not fatal). |
not_found | server | Server: the widget's HTTP endpoints (uploads, attachments, faces) and the REST API. Not sent on the WebSocket. |
conversation_closed | server | Reserved: not sent in this version. |
internal | server | Server: the WebSocket (not fatal) and the REST API (HTTP 500). |
config_not_found | widget | Loader: the config request answered 404. |
frame_blocked | widget | Loader: the chat window didn't connect within 15 seconds. |
bot_disabled | widget | Reserved: not raised in this version. |
network | widget | Loader: the config request failed, or answered with an unexpected status. |
mic_denied | widget | Chat window: starting voice. |
mic_unavailable | widget | Chat window: starting voice. |
camera_denied | widget | Chat window: turning the camera on. |
autoplay_blocked | widget | Reserved: not raised in this version. |
webgl_unavailable | widget | Reserved: not raised in this version. |
upload_rejected | widget | Server: the upload endpoint (HTTP 403 or 413). Shown in the chat; not emitted as an event. |
tool_failed | widget | Loader: a page tool threw, timed out or isn't registered. Reported to the agent, not emitted as an error event (the tool event fires with failed). |
tool_timeout | widget | Reserved: not raised in this version. |
protocol_mismatch | widget | Reserved: not raised in this version. |
origin_not_allowed
From: Server: the config request (HTTP 403) and the WebSocket (fatal, closes with 4403).
When: The page's origin doesn't match the bot's allowed origins (security.allowedOrigins).
What to do: Add the exact origin (scheme, host and port) in the admin panel, under the bot's Security tab, then publish. https://*.example.com covers subdomains but not example.com itself. See Security.
In short: This site isn't in the bot's allowed origins. Add it in the admin panel: Bot > Security > Allowed origins.
bot_unavailable
From: Server: the WebSocket (fatal, closes with 4404).
When: No live bot has this id: it was never published, it's paused, or it was deleted.
What to do: Publish the bot, or set it live again, in the admin panel.
identity_required
From: Server: the WebSocket (fatal, closes with 4403).
When: The bot's identity mode is required and the page sent no user at all.
What to do: Pass user: { id, hash } to boot() (or in window.wirefaceChatSettings), with the hash computed on your server. See Identity verification.
In short: This bot requires identity verification: pass user.id and user.hash to WirefaceChat.boot().
identity_invalid
From: Server: the WebSocket. Fatal in required mode (closes with 4403); otherwise the chat carries on anonymously.
When: user.hash doesn't match user.id (in optional or required mode), identify() sent a bad hash, or identify() tried to sign a different user into a chat a verified user already has.
What to do: Compute HMAC-SHA256(identity secret, user id) as hex on your server, with the current secret (replacing the secret invalidates old hashes). When users sign out, call shutdown({ forget: true }) and boot the chat again.
In short: user.hash doesn't match user.id. Compute HMAC-SHA256(identity secret, user.id) on your server.
rate_limited
From: Server: the WebSocket (too many connections from one IP: fatal, closes with 4429; the other limits: not fatal) and the upload endpoint (HTTP 429).
When: More than 30 chat connections a minute from one IP address, more new conversations with a bot than security.rateLimits.conversationsPerIpPerHour from one IP, more messages than security.rateLimits.messagesPerMinute from one visitor, or more uploads than security.rateLimits.uploadsPerHour.
What to do: Usually a bot or a reload loop. For real traffic behind one IP (an office NAT), raise the bot's limits. Behind a reverse proxy, set TRUST_PROXY=true so each visitor's own IP is used.
In short: Too many requests; slow down and try again shortly.
spend_cap_reached
From: Server: the WebSocket, when voice starts (not fatal).
When: The bot reached one of its daily caps (security.caps: spend, messages or voice minutes; days are UTC). Text replies at a cap are a short "can't chat any more today" message instead of this error.
What to do: Raise or clear the cap in the bot's Security tab, or wait for the next UTC day.
In short: The bot reached today's usage cap set in the admin panel.
voice_capacity
From: Server: the WebSocket, when voice starts (not fatal).
When: The bot already has security.caps.concurrentVoiceSessions voice conversations running.
What to do: Raise the limit, or ask visitors to type for now.
voice_unavailable
From: Server: the WebSocket (not fatal).
When: Voice isn't set up for this bot (off, or its provider connection or model is missing), a person from your team is handling the chat, or the voice engine stopped with an error (the message says why).
What to do: Check the bot's Voice tab: the admin lists what's missing. If the engine stopped, check the provider connection's status and the server log.
session_limit
From: Server: the WebSocket (not fatal).
When: The conversation passed its length limit (about three times security.maxTurnsPerConversation messages).
What to do: Start a new conversation. Raise security.maxTurnsPerConversation if long chats are normal for you.
provider_unavailable
From: Reserved: not sent to widgets in this version.
When: A provider couldn't be reached. Today the visitor sees a "couldn't answer" reply (text) or voice ends with voice_unavailable, and the details go to the server log and the provider connection's status.
What to do: Check the server can reach the provider (firewall, proxy, PROVIDER_BASE_URL_*).
provider_error
From: Reserved: not sent to widgets in this version.
When: A provider refused a request (bad key, no credit, unknown model). The visitor sees a "couldn't answer" reply; the admin panel marks the connection.
What to do: Open Providers in the admin panel and test the connection. See Troubleshooting.
unsupported
From: Server: the WebSocket (not fatal).
When: The widget sent a message type this server doesn't handle.
What to do: Usually a widget newer than the server: update the server, or pin the widget version.
protocol_unsupported
From: Server: the WebSocket (fatal, closes with 4400).
When: The widget speaks a different protocol version than the server.
What to do: Reload the page. If it keeps happening, a cached or pinned widget.js is older or newer than the server.
bad_message
From: Server: the WebSocket (not fatal).
When: A message didn't match the protocol (the message says which field), or the lead form was sent empty.
What to do: Only expected from custom clients. See the protocol.
not_found
From: Server: the widget's HTTP endpoints (uploads, attachments, faces) and the REST API. Not sent on the WebSocket.
When: The bot, image or face asked for doesn't exist (or has been deleted).
What to do: Check the id in the request.
conversation_closed
From: Reserved: not sent in this version.
When: A closed conversation gets a new message. Today the widget starts a new conversation instead.
What to do: Nothing to do.
internal
From: Server: the WebSocket (not fatal) and the REST API (HTTP 500).
When: Something unexpected failed on the server.
What to do: Check the server log around that time (LOG_LEVEL=debug for more detail).
config_not_found
From: Loader: the config request answered 404.
When: No published, live bot has this id: a typo in data-bot, or the bot is unpublished, paused or deleted.
What to do: Copy the id from the admin panel and publish the bot.
In short: No published bot with this id. Check data-bot, and publish the bot in the admin panel.
frame_blocked
From: Loader: the chat window didn't connect within 15 seconds.
When: A Content-Security-Policy on your page blocks the frame (frame-src), the chat window refused to be framed (its frame-ancestors lists the bot's allowed origins, and every page up the frame chain must match: a page shown inside another site's iframe fails), or the network or an extension blocked it.
What to do: Add the chat host to frame-src (see Content-Security-Policy) and check the allowed origins. The browser console names the blocked request.
In short: The chat frame didn't load. A Content-Security-Policy probably blocks it: add the chat host to frame-src.
bot_disabled
From: Reserved: not raised in this version.
When: A paused bot currently shows config_not_found (loader) or bot_unavailable (WebSocket).
What to do: Set the bot live in the admin panel.
network
From: Loader: the config request failed, or answered with an unexpected status.
When: The chat server can't be reached from the browser, a Content-Security-Policy blocks the request (connect-src), or the server answered 5xx.
What to do: Open the config URL from the console message in a browser tab. Add the chat host to connect-src if your page has a CSP.
mic_denied
From: Chat window: starting voice.
When: The visitor (or the browser, or your page's Permissions-Policy) blocked the microphone.
What to do: The visitor can allow it from the address bar. Pages served over plain http never get the microphone. See Troubleshooting.
In short: Microphone permission was denied.
mic_unavailable
From: Chat window: starting voice.
When: The microphone failed for another reason: none connected, in use by another app, or the browser has no audio capture.
What to do: The error message is the browser's own reason.
camera_denied
From: Chat window: turning the camera on.
When: The camera could not be opened: permission denied, no camera, or it is in use.
What to do: As for the microphone. The error message is the browser's own reason.
In short: Camera permission was denied.
autoplay_blocked
From: Reserved: not raised in this version.
When: Browsers only play sound after the visitor interacts with the chat window.
What to do: Start voice from a click inside the chat (its microphone button). See Voice.
In short: The browser blocked sound until the visitor interacts with the chat.
webgl_unavailable
From: Reserved: not raised in this version.
When: Without WebGL2 the chat draws the face as a 2D wireframe instead (and, if even that fails, a still picture). It happens silently.
What to do: Nothing to do. See Troubleshooting.
In short: WebGL2 is not available, so a simpler face is shown.
upload_rejected
From: Server: the upload endpoint (HTTP 403 or 413). Shown in the chat; not emitted as an event.
When: Image uploads are off for this bot (or its brain can't see images), or the image is over vision.uploads.maxMB.
What to do: Turn uploads on in the bot's Vision tab, or send a smaller image.
tool_failed
From: Loader: a page tool threw, timed out or isn't registered. Reported to the agent, not emitted as an error event (the tool event fires with failed).
When: Your registerTool handler threw or took longer than its timeout.
What to do: Check the handler; see Client tools.
tool_timeout
From: Reserved: not raised in this version.
When: Timeouts are reported as tool_failed.
What to do: Nothing to do.
protocol_mismatch
From: Reserved: not raised in this version.
When: Version mismatches between the server and the widget show as protocol_unsupported.
What to do: Nothing to do.
WebSocket close codes
The widget's WebSocket (/v1/widget/ws) closes with these codes (4000 to 4999 are application codes). A fatal error message comes first and says why. After a fatal error the chat stops reconnecting until the page is reloaded; after 4401, 4403 and 4404 it doesn't reconnect either. Other closes reconnect with backoff (from half a second up to 10 seconds, with jitter). The server closes every socket with 1001 when it shuts down.
| Code | Name | When |
|---|---|---|
4000 | ENDED | Sent by the widget itself when it reconnects to pick up a republished bot. The server does not use it. |
4001 | SUPERSEDED | Reserved: not used in this version. |
4400 | BAD_MESSAGE | The protocol version is not supported, a message was over 256 KB, or the URL had no bot. |
4401 | UNAUTHORIZED | No hello within 5 seconds, or the first message wasn't a hello. (The admin panel's live socket also uses it when you're not signed in.) |
4403 | FORBIDDEN | The origin is not allowed, or (with identity mode required) the page sent no identity or one that doesn't check out. |
4404 | NOT_FOUND | No live bot with this id. |
4408 | IDLE | Reserved: not used in this version. |
4429 | RATE_LIMITED | Too many connections from one IP address (30 a minute). |
4500 | INTERNAL | Reserved: not used in this version. |