{
"errorType": "VALIDATION_ERROR",
"message": "You cannot have both hidden actions and visible actions",
"code": "CONFLICTING_ACTIONS_CONFIG",
"severity": 3,
"error": "You cannot have both hidden actions and visible actions"
}
Handling embed errors
|
Important
|
In Visual Embed SDK v1.53.0 and later, For more information, see Error severity levels. |
The ThoughtSpot Visual Embed SDK provides a layered approach to error handling. EmbedEvent.Error is a real-time outbound event that the embedded ThoughtSpot iframe emits to the host app. It signals that something went wrong inside the SDK, inside the embedded app (the iframe), or because the host sent an invalid HostEvent payload.
Unlike most embed events, which the SDK caches and replays to late subscribers, EmbedEvent.Error is not cached or replayed. Every emission is independent, so you must register a handler before an error occurs.
EmbedEvent.Error fires per embed component. Register the handler before you call render().
Trigger sources🔗
Embed errors surface through distinct channels for the following failure categories:
SDK or configuration validation🔗
When SDK or configuration errors occur, the internal handleError(errorDetails) method in the embed component:
-
Sets
isError = true, which permanently blocks futurerenderIFramecalls on this instance. -
Calls
executeCallbacks(EmbedEvent.Error, { severity: SEV3, …​errorDetails }). The default severity isSEV3unless the error sets its own. -
Logs via
logger.error(errorDetails).
| Condition | code | severity | message emitted |
|---|---|---|---|
|
|
|
|
|
|
|
|
Both |
|
|
|
Both |
|
|
|
|
|
|
|
|
|
|
|
Auth failure during |
|
| The message of the caught auth or login error, or |
The SDK emits these errors with the following payload:
The error field is retained for backward compatibility. For more information about the payload fields, see EmbedErrorDetailsEvent.
HostEvent validation🔗
When the host sends a HostEvent with an invalid payload or a context mismatch, the event bridge validates it against the HostEvent schema. On failure, the SDK emits EmbedEvent.Error with code embedErrorCodes.HOST_EVENT_VALIDATION. The trigger() call also rejects with the validation error.
{
"type": "Error",
"data": {
"errorType": "VALIDATION_ERROR",
"message": "<human-readable description of what field failed>",
"code": "HOST_EVENT_VALIDATION",
"error": "<human-readable description of what field failed>"
},
"status": "end",
"severity": 3
}
|
Important
|
If |
Runtime filter or cross-filter errors🔗
Filter operations can fail inside the iframe with typed errors:
eventErrorType | Typical message pattern |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Network events🔗
A global listener for the browser offline event on window emits EmbedEvent.Error with a different payload shape:
{
"errorType": "NETWORK",
"message": "Network not Detected. Embed is offline. Please reconnect and refresh",
"code": "NETWORK_ERROR",
"severity": 2,
"offlineWarning": "Network not Detected. Embed is offline. Please reconnect and refresh"
}
Error types🔗
EmbedEvent.Error fires when the following types of errors occur:
| Error type | Description |
|---|---|
| API call failure. This error occurs when an API request is blocked. Example:
|
| Error in presenting a Liveboard or visualization in full-screen mode.
|
| Error in updating filter values. This error occurs when a single-value filter is applied to a Liveboard and the user tries to update this filter with multiple values.
|
| Error in applying filter due to a non-existent filter.
|
| Error due to an invalid date value in a filter. For example, if the column name is
|
| Error due to an invalid operator in filter properties. For example, if you try to apply filters on the
|
Error severity levels🔗
The EmbedEvent.Error payload includes a severity field that categorizes errors into three levels:
| Severity | Description | Recommended handling |
|---|---|---|
| The embed is down: nothing usable is on screen, for example, because of an SDK initialization failure, a login failure, or an app crash. | Consider tearing down the embed and re-initializing, or showing a custom error message to the user. |
| An error was shown to the user; the embed still works. | Log the error for monitoring. No immediate action is required unless the error indicates a persistent issue. |
| Everything else, including validation of the embedder’s own input. | Log the error for debugging. These errors are typically not user-facing and can often be ignored if the application is functioning correctly. |
The severity field is an optional numeric value that maps to the EmbedErrorSeverity enum: SEV1 is 1, SEV2 is 2, and SEV3 is 3. If an error does not set a severity, the SDK defaults to SEV3.
{
"type": "Error",
"data": {
"errorType": "API",
"error": {
"message": "..."
},
"severity": 2
}
}
|
Note
|
The |
Payload shapes🔗
EmbedEvent.Error emits one of the following payload shapes:
// SDK / auth error
{
errorType: string;
message: string | string[];
code: string;
severity?: number;
error?: unknown; // retained for backward compatibility
}
// HostEvent validation error
{
type: 'Error';
data: { errorType: string; message: string; code: 'HOST_EVENT_VALIDATION'; error: string };
status: string;
severity?: number;
}
// Filter / runtime error (from embedded app)
// — matches one of the eventErrorType patterns above
// Network offline
{
errorType: 'NETWORK';
message: string;
code: 'NETWORK_ERROR';
severity: number;
offlineWarning: string;
}
How to subscribe🔗
The following example shows how to handle each EmbedEvent.Error payload shape.
import { LiveboardEmbed, EmbedEvent } from '@thoughtspot/visual-embed-sdk';
const embed = new LiveboardEmbed('#container', {
liveboardId: 'your-liveboard-id',
});
// Register BEFORE render() — errors can fire during initialization
embed.on(EmbedEvent.Error, (payload) => {
// SDK/auth error
if (payload?.error) {
console.error('[SDK Error]', payload.code, payload.error);
return;
}
// HostEvent validation error (your payload is malformed)
if (payload?.data?.code === 'HOST_EVENT_VALIDATION') {
console.error('[HostEvent validation failed]', payload.data.message);
return;
}
// network offline
if (payload?.offlineWarning) {
showOfflineBanner(payload.offlineWarning);
return;
}
// runtime filter/action error from the iframe
console.warn('[Embed runtime error]', payload);
});
embed.render();
Handling HostEvent errors🔗
The following example shows how to handle errors from a trigger() call.
import { HostEvent } from '@thoughtspot/visual-embed-sdk';
async function updateRegionFilter() {
try {
const result = await embed.trigger(HostEvent.UpdateRuntimeFilters, [
{ columnName: 'Region', operator: 'EQ', values: ['West'] },
]);
// Timeout is a resolve, not a reject — check explicitly
if (result instanceof Error) {
console.error('HostEvent timed out:', result.message);
return;
}
console.log('HostEvent succeeded:', result);
} catch (err) {
// Rejection = iframe returned an explicit error in the response
console.error('HostEvent rejected by iframe:', err);
}
}
Error handling guidelines🔗
| Error category | Detection and recovery |
|---|---|
SDK init config error | Detection mechanism: Payload/data: Recovery action: Fix the configuration. Destroy the embed, then create and render a new instance. |
Auth failure (SDK layer) | Detection mechanism: Payload/data: Recovery action: Check |
Auth failure (iframe layer) | Detection mechanism: Recovery action: Show a login prompt. Destroy the embed, then create and render a new instance. |
Session expired | Detection mechanism: Recovery action: Refresh token. Use |
Idle session timeout | Detection mechanism: Recovery action: Use |
Third-party cookies blocked | Detection mechanism: Recovery action: Switch to |
User logout | Detection mechanism: Recovery action: Redirect to login or clear state. |
Duplicate token | Detection mechanism: Payload/data: Recovery action: Always return a fresh token from |
Invalid token | Detection mechanism: Payload/data: Recovery action: Verify token generation on the server. |
Network offline | Detection mechanism: Payload/data: Recovery action: Show offline UI. Reconnect and reload. |
HostEvent validation error | Detection mechanism: Payload/data: Recovery action: Fix the |
HostEvent timeout (30 seconds) | Detection mechanism: Payload/data: Recovery action: Check if the iframe is still mounted. Call |
HostEvent iframe rejection | Detection mechanism: Payload/data: Error from iframe Recovery action: Inspect the rejection payload. See the HostEvent validation error row. |
Filter errors at runtime | Detection mechanism: Payload/data: Recovery action: Fix filter parameters. Validate against current Liveboard/answer filters. |
Destroying an embed instance🔗
To remove an embedded ThoughtSpot component, for example, during route changes, error recovery, or cleanup in single-page apps, call embed.destroy(). This is the only supported way to tear down an embed instance.
Calling embed.destroy() performs the following cleanup steps in order:
-
Removes fullscreen change handlers.
-
Disconnects the resize observer.
-
Unsubscribes window-level event listeners registered by the embed.
-
Removes any pre-render wrappers created during initialization.
-
Sends an internal notification to the embedded iframe so that it can release its own resources.
-
Removes the iframe DOM node from the page.
If the embed has not rendered yet, destroy() skips steps 5 and 6.
After destroy() completes, the embed instance is no longer usable. To re-embed, create a new instance and call render() again.
After an SDK or configuration error, the embed instance blocks all further render() calls. To recover, destroy the instance, fix the cause, and create a new one.
Example: Destroy and re-create🔗
import {
LiveboardEmbed,
HostEvent,
EmbedEvent,
} from '@thoughtspot/visual-embed-sdk';
// Create and render the embed
const embed = new LiveboardEmbed(document.getElementById('embed-container'), {
liveboardId: 'd084c256-e284-4fc4-b80c-111111111111',
});
embed.render();
// Later, tear it down
embed.destroy();
// To re-embed, create a new instance
const newEmbed = new LiveboardEmbed(document.getElementById('embed-container'), {
liveboardId: 'd084c256-e284-4fc4-b80c-111111111111',
});
newEmbed.render();
Wait for iframe cleanup🔗
By default, destroy() sends the internal teardown notification to the iframe and removes the DOM node immediately, without waiting for the iframe to finish its own cleanup.
If your application requires the iframe to complete its cleanup before the DOM node is removed, set waitForCleanupOnDestroy to true in the init() configuration:
import { init, AuthType } from '@thoughtspot/visual-embed-sdk';
init({
thoughtSpotHost: 'https://<your-ts-instance>.thoughtspot.cloud',
authType: AuthType.TrustedAuthTokenCookieless,
// ...other init options
waitForCleanupOnDestroy: true,
cleanupTimeout: 5000, // milliseconds; optional
});
| Parameter | Default | Description |
|---|---|---|
|
| When |
|
| The maximum time, in milliseconds, that |
|
Warning
|
Do not call |
Best practices🔗
-
Always register an event listener for
EmbedEvent.Erroron your embed instance to capture and handle errors emitted by the embedded ThoughtSpot application. RegisterEmbedEvent.Errorbefore callingrender(). -
Inspect and categorize error payloads. The error event provides a payload with fields such as
errorType,message, andcode. Do not assume thatpayload.erroralways exists. Offline errors useofflineWarning, and validation errors usecode. -
Do not destroy the embed for every error. Inspect the error first to determine whether you need to display a host fallback page. Not all errors are fatal, and ThoughtSpot handles some failures internally. Destroy the embed only when the error leaves it unusable. For more information, see Destroying an embed instance.
-
Call
embed.destroy()when you remove the embed container, navigate away from the page, or unmount the component. Do not reuse a destroyed instance. Create a new one instead. -
Provide contextual and user-friendly error messages based on the
errorTypeand error details. Avoid exposing raw error objects or stack traces to your application users. -
Enable
useHostEventsV2: truein development/staging to surfaceHostEventpayload errors early. -
Log errors for diagnostics.
-
Simulate error scenarios during development, such as network failures and invalid filters, to verify that your error handling logic works as expected.
-
Do not set
shouldBypassPayloadValidation: truein production environments. Validation errors become invisible console warnings. -
Do not call
trigger()beforerender(). The SDK emits anEmbedEvent.Errorwith theRENDER_NOT_CALLEDcode and returnsnull.
Try it out in the Visual Embed Playground🔗
Try out the embed events in the Visual Embed Playground and preview changes.
Additional resources🔗
-
To identify and log errors, use the error types and error codes. For more information, see EmbedErrorDetailsEvent and EmbedErrorCodes.
-
For information about the supported event objects and examples, see EmbedEvent.