19

I have a shiny app and when I run it I get an error saying that an object of type ‘closure’ is not subsettable. What is that and how can I fix it?

Note: I wrote this question as this comes up a lot, and the possible dupes are either not shiny related or so specific that it is not obvious that the answers are broadly applicable.

John Paul
  • 12,196
  • 6
  • 55
  • 75
  • 2
    still a dupe, the same error is occurring, you can't subset a closure (function), has nothing to do with shiny `(function() {})$x` and the explanation is unnecessary, `reactive` returns a function, so `mfDF$x` is trying to subset a function which you cannot do – rawr Nov 16 '16 at 04:06
  • I tend to agree with @rawr in that the error is not related to shiny, it's just that it is encountered a lot within shiny. The explanation in your answer is useful, however. – SymbolixAU Nov 16 '16 at 04:19
  • 2
    I think the difference is that many new shiny users will not think of reactive `data.frames` etc as functions but rather just as `data.frames`. So when they see a non-shiny answer that discusses functions it is not clear how that applies. That said, I agree it is the same problem, but I think a different question is useful as well. – John Paul Nov 16 '16 at 04:23
  • why then arent shiny users reading the manual? `?shiny::reactive` says `Value a function, wrapped in a S3 class "reactive"` – rawr Nov 16 '16 at 04:38

1 Answers1

42

See also this question which covers this error in a non-Shiny context.

How to fix this:

This is a very common error in shiny apps. This most typically appears when you create an object such as a list, data.frame or vector using the reactive() function – that is, your object reacts to some kind of input. If you do this, when you refer to your object afterwards, you must include parentheses.

For example, let’s say you make a reactive data.frame like so:

MyDF<-reactive({ code that makes a data.frame with a column called “X” })

If you then wish to refer to the data.frame and you call it MyDF or MyDF$X you will get the error. Instead it should be MyDF() or MyDF()$X You need to use this naming convention with any object you create using reactive().

Why this happens:

When you make a reactive object, such as a data.frame, using reactive() it is tempting to think of it as just like any other non-reactive data.frame and write your code accordingly. However, what you have created is not really a data.frame. Rather, what you have made is instructions, in the form of a function, which tell shiny how to make the data.frame when it is needed. When you wish to actually use this function to get the data.frame you have to use the parenthesis, just like you would any other function in R. If you forget to use the parenthesis, R thinks you are trying to use part of a function and gives you the error. Try typing:

plot$x

at the command line and you will get the same error.

You may not see this error right when your app starts. Reactive objects have what is called “lazy” evaluation. They are not evaluated until they are needed for some output. So if your data.frame is only used to make a plot, the data.frame will not exist until the user sees the plot for the first time. If when the app starts up the user is required to click a button or change tabs to see the plot, the code for the data.frame will not be evaluated until that happens. Once that happens, then and only then will shiny use the current values of the inputs to run the function that constructs the data.frame needed to make the plot. If you have forgotten to use the parentheses, this is when shiny will give you the error. Note that if the inputs change, but the user is not looking at the plot, the function that makes the data.frame will not be re-run until the user looks at the plot again.

Community
  • 1
  • 1
John Paul
  • 12,196
  • 6
  • 55
  • 75
  • Nice answer. I also run into this error, some how figured out the issue. But nice for people who may run into this issue. :) – Kumar Manglam Nov 16 '16 at 03:57
  • 1
    Great explanation. I want to reach across the internet and hug you because this saved me – orrymr May 18 '20 at 09:50