In R Shiny, when is an error really an error?

R Shiny is a really super gift to R users and to the world in general. Essentially, it allows you to democratize your code to others in a user friendly way, meaning non R-coders can take advantage of functionality you’ve developed.

But it can look a bit unprofessional and ‘hacky’ when R’s red error messages of death flow through from the server side and appear in the user interface unnecessarily. For examples, this looks pretty bad to an end user:

There are two ways that you can easily improve the end user experience and avoid users reaching out to you about errors that are not really errors, but just consequences of the users input choices.

Let’s say that you have created an app, and the app filters a data set based on certain user inputs and then spits out some statistics on the filtered data.

Let’s say that on the server side a reactive filtered dataframe is being created that will be used to calculate the statistics — lets call it filtered_df(). One common possibility is that the user has selected so many filters that there is no data left in filtered_df() and it is in fact a dataframe with zero rows.

Option 1 — Writing a specific error message

One option for how to handle this is to use the stop() function to write a specific error message for this occurrence. You could, for example, do this:

checked_filtered_df <- shiny::reactive({

if (nrow(filtered_df()) == 0) {
stop("No data available for chosen filters!")
} else {

In the event where the user has filtered out all the data, this will return a red error message like the one above, except it will contain the specific language “Error: No data available for chosen filters!”. That’s a little better, but it still looks bad to an end user in my opinion. Plus — is it really an error? I don’t think so — nothing is actually wrong with your code. I’m not a fan of using stop() in this way.

Option 2 — using Shiny’s awesome validation functions

The Shiny validate() function is really good for this sort of situation. It can perform a test on your server outputs and you can tell it what to display in the event that the test fails. It displays it in much less scary grey text and, importantly, it does not call it an error.

Within validate(), you can use the need() function to set a test criterion and write a message to display in the event of a test failure. Rewriting the above code to use validate() instead of stop() would look like this:

checked_filtered_df <- shiny::reactive({
shiny::need(nrow(filtered_df()) != 0,
"No data available for chosen filters!")

Now, when the user filters down to an empty dataset, the following will appear in the UI:

This is much less alarming, and much more clear to the end user that they have filtered the dataset down to nothing.

If you haven’t done anything like this before in Shiny, it’s worth some further study. With every new release Shiny contains more and more ways to smooth out the user interface and to control for anticipated issues. There’s more technical detail on validate() here.

Leave a Reply

%d bloggers like this: