It’s quite frustrating when we are all set to embed your beautiful dashboard on our awesome web application and all we get is a nasty “414 Request-URI Too Long” error.
This is one of the cases where the error message tells us exactly what’s wrong, but it’s very difficult to figure out where the problem is and how to fix it. So this post is here to the rescue!
It happens when we want to apply filters before loading the viz, but we are passing way too many parameters and filters. When Tableau’s JS API is ready to send an initial message to the VizQL process on Tableau Server or Online, it sends a GET request (potentially) with a huge URI, much longer than what’s supported in the RFC 7231 specification.
For example, let’s assume this is the initial view we want to initialise on our app:
- Viz URL: https://<my_server>/myworkbook/myview
- Options: hideTabs, hideToolbar
- Filters: “Region”: [“Central”, “North”] , “OrderID”: [“NN_01”, “NN_05”, “NN_09”]
In this case, Tableau will send a GET request to the server with the following URL:
As you can see, this URI can get really long. This is not a Tableau limitation, but rather the way web technology works :)
So, are there any Workarounds?
The first thing we must ask ourselves is whether it really make sense to send such a long filter on init. Could we perhaps design the dashboard in a way that by default it shows the correctly filtered view on load?
I’d say that 99% of the cases, this is indeed the solution. So, from a JS API perspective, we don’t need to pass any filters via code, because the viz is already going to return the subset of data we need.
But sometimes that’s really not possible due to some very peculiar UX workflow or compliance requirement. In this case, the workaround is to apply filters after loading the viz.
Apply Filters After Loading the Viz
When we apply filters after loading the viz, it uses a POST request, instead of GET, which will allow us to pass a large amount of parameters in the request.
Here’s what we’ll do to properly embed Tableau in this case:
a) Configure your app to initialise the Tableau embedded viz pointing to a url of the dummy blank sheet that lives in the same workbook (yes, you need to publish this blank sheet on the same workbook, just for this purpose). This workbook should not contain anything at all in it. We should even hide its title.
b) Right after the initial view has been fully initialised the blank frame, we will leverage the onFirstInteractive( ) function to automatically trigger a call to the JS method to switch to the actual sheet we want to embed and, right after that, automatically call the the JS filter async function. We can use JS Promises (i.e. “.then”) to chain these two calls, for example:
a) Initialise the view passing a dummy filter, so that it renders a blank canvas. For example “Order ID” : “-1” , where “-1” does not exist in the database. We just make sure the dummy filter is targeting an indexed database field, so that the query overhead is minimal when using this approach.
b) Then we call the filter right after the initial view has been fully initialised, also leveraging the the onFirstInteractive( ) function which is always automatically fired.
Either way, now the viz will firstly render a blank canvas, but an instant later switch to show the filtered view.
I’ve recoded a short video showing option 2 and the tools I use for troubleshooting: