Tableau Embedded Error Handling— the Nice and Ugly ways

Eski's data stories
6 min readJul 4, 2023

Anyone writing software knows that error handling is a must. And this isn’t any different when embedding Tableau content in third-party apps and portals. Depending on your goals the approach can get ugly!

why ugly animals are cute

The main reasons why the embedded content may fail to load are (github issue discussion):

  1. Connected App / jwt authentication errors: the secret is deleted, the connected app is disabled, the jwt is malformed
  2. Invalid URL: you are embedding a Viz whose URL changes (it gets deleted and then re-published with a different URL for example)
  3. Connectivity issue between the Tableau Server or Cloud environment and the browser of the end-user.

This article introduces some ideas to tackle each of them. Thanks tpayne for the help!

1- Connected App authentication errors

This is the easiest type of error to catch as there’s native support in the Embedding API v3.6+ for CA-related issues and is well documented here.

The idea is to watch out for whether the event type TableauEventType.VizLoadError has fired to retrieve and research the error code. You’ll find all Connected Apps-related error codes with possible underlying root causes here. For example:

common types of jwt auth (Connected Apps) issues

2- Invalid URL

A common issue is when the url of the object you’re trying to embed isn’t valid. Tableau expects this syntaxhttps://<server-address>/t/<site-name>/<workbook-name>/<view-name> , but oftentimes people mistype the site, workbook or view names. Maybe the author has deleted and replublished the workbook or view with a different name.

This highlights a very important solution design best practice: the portal should be as dynamic as possible, in a way that the content dysplayed to the user is ever changing and controled by the permissions set to the content access in Tableau itself (e.g. via group membership). This “trick” is well explained in Tableau’s embedding Playbook:

So this problem shouldn’t really ever manifest itself if you create a dynamic portal that leverages the Rest API to check what content a user can see and build the url programmatically.

This would be a backend server call and won’t suffer from cross-domain issues. NB: you cannot perform this check client-side, as the browser will complain that you’re trying to access the contents of a server from a different domain as compared to the portal’s domain. Unless you place your Tableau Server and your portal in the same domain (e.g. via a proxy), as described in my other article, you’ll have trouble checking this client-side. At the time of writing this article, this isn’t yet possible with Tableau Cloud.

In summary, using this technique you will be able to:

a) confirm the Server is up and running

b) construct the URL based on the actual names currently used in the server.

Side-comment: Doing this will also allow you to monetize the solution down the line, because you’ll be placing users in different groups with different access permissions to see different sets of content, which is the main building block for monetization, for example:

Having said all that, I’m pretty sure some of you reading this article aren’t building a large embedded solution and really only want to embed a small set of dashboards and would be happy to hard-code these URLs and take the risks. If that’s you, keep reading!

3- Connectivity issue between the Tableau Server or Cloud environment and the browser of the end-user

Let’s say you do confirm the URL is valid with a REST call from the back-end, but the client itself may be experiencing a connectivity issue to the server. Or you really have good reasons to not want to make server-side checks.

We also need to remember that while we embed with the Embedding Api which is leveraging web components, the result is always an iframe and hence, from a Tableau perspective, we can’t actually do much about what happens in the iframe at all. The iframe src is third-party domain, so it’s not easy to check its contents.

To avoid this cross-domain issue altogether you may use the trick I’ve mentioned above to move both the portal and Tableau Server to the same domain (not possible yet with TabCloud, watch this space ;).

Perhaps you still expect to catch a 404 error, but this doesn’t seem as easy as said. Here’s something tpayne has found:

The 404 Page is handling an HTTP Status Code, which is only included in the server’s response sent to the browser, but not in the actual window and document objects of the DOM that javascript may access.

This means that while you certainly can collect the status-code and take appropriate actions, you may only do so when your javascript is receiving the response, such as with a jQuery.ajax() request or an XmlHttRequest to load your “iframe”.

But we can’t do that, as the portal is on a different domain as the tableau iframe. And Tim continues:

The only way you can find it, if it you can access iframe.innerHTML and search for content. Which we can’t as you can’t inspect iframe code when cross-domain. If we’re same domain — checking the contents of the iframe would work. If we’re not, then we’re out of luck due to how browsers/security work.

So, how do you catch 404 or similar connectivity errros client side?

This is where it gets super ugly 🫣 : we’ll use a timer function to give it some time for the Tableau embedded content iframe to load and check whether it has worked or not. This is by no means best practice, but may work for some small solutions:

a) create a variable to track if the viz has loaded with default value = false:

b) add an event listener to track when the “First Viz Size is Known” and set the variable above to true. This event fires slightly before “FirstInteractive”, so it’s a better option.

FirstVizSizeKnown event will only be triggered if the connectivity between client (browser) and the Tableau environment is ok, auth went ok and the workbook is found (i.e. not only means the url syntax is valid, but also the viz really exists on the server):

c) now the 🫣 ugly bit: set a timer to check if the variable is true or false after 4sec (tweak the delay it as needed).

If false, we’d supect it hasn’t loaded, so you can decide to, say, show a static image or redirect the user to some 404 or another page:

🤮

Not elegant, but it’s a side effect of dealing with iframes. Again, if you can avoid this altogether by running your Tableau Server on the same domain as the portal, maybe you can make some proper checks inside the iframe itself.

I’d imagine there are other ways out there to deal with theses issues, so send me a comment on your suggestions and if you liked this post, give me 50 👏 and subscribe to receive my next posts.

--

--