Skip to content

Troubleshooting

This page covers the most common issues when integrating the <saytv-chat> widget and how to resolve them.

Listening for Errors

The widget emits an stv:error event whenever something goes wrong. Always listen for this event during development to catch issues early.

Vanilla JS

js
const chat = document.querySelector('saytv-chat');

chat.addEventListener('stv:error', (e) => {
  console.error('SayTV error:', e.detail.error.message);
  // e.detail.error.code - HTTP status code (if applicable)
});

React

tsx
<SayTVChat
  appId="your-app-id"
  onError={(e) => console.error('SayTV error:', e.detail.error)}
/>

Vue

vue
<SayTVChat
  app-id="your-app-id"
  @error="(e) => console.error('SayTV error:', e.detail.error)"
/>

The error payload includes a message string and an optional code number (the HTTP status code, when the error came from an API call).

Common Issues

Widget Not Rendering

Symptom: The <saytv-chat> element is in the DOM but nothing appears on screen.

Check the import. The widget must be imported before it can render. Make sure your script import runs before the element is parsed, or use type="module":

html
<script type="module">
  import '@saytv/chat-sdk/widget';
</script>

<saytv-chat app-id="your-app-id"></saytv-chat>

Check that app-id or apiurl is set. The widget needs an API connection to load content. Without either attribute, it cannot initialize.

html
<!-- Using app-id (recommended) -->
<saytv-chat app-id="your-app-id"></saytv-chat>

<!-- Or a direct API URL -->
<saytv-chat apiurl="https://your-api.example.com/api/v3"></saytv-chat>

Check for duplicate registrations. If you import the widget script more than once, the custom element may fail to register. Make sure @saytv/chat-sdk/widget is only imported once in your application.

Check the container dimensions. The widget defaults to 450px wide and 850px tall. If the parent container has overflow: hidden, height: 0, or display: none, the widget may be present in the DOM but not visible. Inspect the element in DevTools and confirm it has layout dimensions.

Authentication Token Not Working

Symptom: You pass auth-token but the user is not logged in, or you see "JWT authentication failed" in the stv:error event.

Verify the token is valid. The SDK exchanges your JWT for a SayTV session token. If the JWT is expired, malformed, or signed with the wrong key, this exchange will fail. Decode your token at jwt.io and check the exp claim.

Set built-in-auth="false". When providing an external token, disable the built-in login UI so the widget does not show its own login screen:

html
<saytv-chat
  app-id="your-app-id"
  auth-token="eyJhbGciOiJIUzI1NiIs..."
  built-in-auth="false"
></saytv-chat>

Handle token refresh. The auth-token attribute is reactive. When the user's token is refreshed in your app, update the attribute and the SDK will re-authenticate automatically.

js
const chat = document.querySelector('saytv-chat');
chat.setAttribute('auth-token', freshToken);

Check for 401 errors. If the session token expires mid-session, the SDK automatically logs the user out and emits stv:user-logout. Listen for this event to trigger a token refresh in your application:

js
chat.addEventListener('stv:user-logout', () => {
  // Fetch a fresh token from your backend and re-set it
  const newToken = await refreshToken();
  chat.setAttribute('auth-token', newToken);
});

Theme Not Applying

Symptom: You set CSS custom properties but the widget ignores them.

Use inline styles on the element itself. The widget renders inside a Shadow DOM, so external stylesheets cannot reach it. CSS variables must be set as inline styles on the <saytv-chat> element:

html
<!-- This works -->
<saytv-chat
  app-id="your-app-id"
  style="--stv-color-primary: #4f46e5;"
></saytv-chat>
css
/* This does NOT work - Shadow DOM blocks it */
saytv-chat {
  --stv-color-primary: #4f46e5;
}

Set the theme attribute for dark mode. The dark theme is not just an inversion of colors. Use the theme attribute to switch the entire palette:

html
<saytv-chat app-id="your-app-id" theme="dark"></saytv-chat>

Admin panel theme may override defaults. If your SayTV admin panel has a custom theme configured, those values override the CSS defaults. To override everything, use inline style attributes on the element - they always take highest priority.

Events Not Firing

Symptom: You added an event listener but callbacks never run.

Listen on the element, not document. Events are dispatched on the <saytv-chat> element itself. While they do bubble and cross the Shadow DOM boundary (composed: true), attaching the listener directly to the element is the most reliable approach:

js
// Correct
const chat = document.querySelector('saytv-chat');
chat.addEventListener('stv:ready', () => { /* ... */ });

// Also works (events bubble)
document.addEventListener('stv:ready', () => { /* ... */ });

Wait for the element to be defined. If you add a listener before the widget script loads, the element exists but is not yet upgraded. The stv:ready event fires once the widget is fully initialized. Use customElements.whenDefined() if you need to run code after the element is available:

js
await customElements.whenDefined('saytv-chat');
const chat = document.querySelector('saytv-chat');
chat.addEventListener('stv:ready', () => {
  console.log('Widget is ready');
});

Check the event name prefix. All SDK events are prefixed with stv:. Make sure you include the prefix:

js
// Correct
chat.addEventListener('stv:message-sent', callback);

// Wrong - will never fire
chat.addEventListener('message-sent', callback);

Network and Timeout Errors

Symptom: The widget shows a loading state or you see timeout errors in the stv:error event.

Check the API URL. If using apiurl directly, verify it points to the correct endpoint. The URL should include the /api/v3 path prefix.

Check for CORS issues. Open your browser's DevTools Network tab and look for blocked requests. If your site's origin is not allowed by the SayTV API, requests will fail silently. Contact your SayTV administrator to add your domain to the CORS allowlist.

Check your network. Slow or unstable connections may cause timeout errors. The real-time messaging layer will also fail to connect on restricted networks.

Widget Flashes Login Screen

Symptom: When using external JWT auth, the login screen briefly appears before the authenticated content loads.

This happens when there is no cached session. On the first visit, the SDK must exchange the JWT token before it can show content. Set built-in-auth="false" to suppress the login screen. The widget will show a loading indicator during the token exchange instead:

html
<saytv-chat
  app-id="your-app-id"
  auth-token="eyJhbGciOiJIUzI1NiIs..."
  built-in-auth="false"
></saytv-chat>

On subsequent page loads within the same session, the SDK restores the cached session and renders content instantly without the loading state.

Session Lost on Page Reload

Symptom: The user has to log in again after refreshing the page.

The SDK stores authentication state for the duration of the browser tab session. Sessions are cleared when the tab is closed.

If you are using external JWT auth, make sure you always pass the auth-token attribute on page load. The SDK will hydrate from cache and refresh the session in the background, so there is no visible interruption.

If you are using the built-in auth, the session restores automatically within the same tab. Users will need to log in again in a new tab or after closing the browser.

Getting Help

If you have checked this page and are still stuck, reach out to SayTV support with the following information:

  • The stv:error event payload (message and code)
  • Your app-id or apiurl
  • The browser and version
  • Whether the issue is reproducible in an incognito window

SayTV Chat SDK Documentation