Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsonlite warning with shiny 1.4.0 #2673

Open
stla opened this issue Oct 18, 2019 · 13 comments
Open

jsonlite warning with shiny 1.4.0 #2673

stla opened this issue Oct 18, 2019 · 13 comments

Comments

@stla
Copy link

stla commented Oct 18, 2019

Hello,

Consider this app:

library(shiny)
library(ggplot2)

ui <- fluidPage(
  radioButtons("type", "Type of plot", choices = c("density", "boxplot")),
  plotOutput("plot")
)

server <- function(input, output){
  output[["plot"]] <- renderPlot({
    if(input$type == "density"){
      ggplot(iris, aes(Sepal.Length)) + geom_density()
    }else{
      ggplot(iris, aes(x = "", y = Sepal.Length)) + geom_boxplot()
    }
  })
}

shinyApp(ui, server)

When you select the radio button "boxplot", this message appears in the R console:

Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.

It is caused by x = "" in the aes. If I remove this argument, there's no warning anymore.

This message didn't appear with shiny < 1.4.0.

@harrismcgehee
Copy link

Similar experience with any single x axis item:

library(shiny)
library(ggplot2)

ui <- fluidPage(
            tabsetPanel(
                tabPanel("no message", plotOutput("quietPlot")),
                tabPanel("generates `Input to asJSON` message", plotOutput("noisyPlot"))
            )
)

# Define server logic required to draw cols
server <- function(input, output, session) {
    output$quietPlot <- renderPlot({
        ggplot(
            data = data.frame(z = c("a", "b"), n = c(1, 2)),
            aes(x = z, y = n)
        ) + geom_col()
    })
    output$noisyPlot <- renderPlot({
        ggplot(
            data = data.frame(z = c("a"), n = c(1)),
            aes(x = z, y = n)
        ) + geom_col() 
    })
}

shinyApp(ui = ui, server = server)

@jntrcs
Copy link

jntrcs commented Apr 16, 2020

Also receiving this warning whenever x-axis is reduced to single factor.

@kaijagahm
Copy link

I am getting this warning message when I use onRestore and onBookmark. When I run the same app without those functions, the warning disappears.

@wch
Copy link
Collaborator

wch commented Jan 22, 2021

@kaijagahm Can you file a new issue, with a minimal reproducible example?

For the others that have experienced this issue, when I run the example apps, I don't see the message. It's possible that it has been fixed since the issue was originally filed. If you still see that message, please provide the output of sessionInfo() or sessioninfo::session_info().

@SigurdJanson
Copy link

I am not sure this issue is limited to ggplot. I have the same warning whenver I the value argument is a named vector. The problem is there even in shiny 1.6 (session info below). Once I put unname() around it, it works.

I'd prefer if the update-function would just ignore the names in the vector.

library(shiny)

ui <- fluidPage(
    titlePanel("as JSON Warning Sample"),
    mainPanel(
       sliderInput("inpSlider", "Just another value", 1, 10, 5),
       actionButton("btnReset", "Reset to 1")
    )
)

server <- function(input, output, session) {
    observeEvent(
        input$btnReset, 
        {    # NAMED VECTOR CAUSES THE WARNING
             updateSliderInput(session, "inpSlider", value = c(a = 1)) 
        })
}

shinyApp(ui = ui, server = server)
> sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19041)

Matrix products: default

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] shiny_1.6.0

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.6        withr_2.4.1       digest_0.6.27     later_1.1.0.1    
 [5] mime_0.9          R6_2.5.0          jsonlite_1.7.2    lifecycle_0.2.0  
 [9] xtable_1.8-4      magrittr_2.0.1    cachem_1.0.1      rlang_0.4.10     
[13] promises_1.1.1    jquerylib_0.1.3   bslib_0.2.4       ellipsis_0.3.1   
[17] tools_4.0.3       tinytex_0.29      rsconnect_0.8.16  httpuv_1.5.5     
[21] xfun_0.20         fastmap_1.1.0     compiler_4.0.3    htmltools_0.5.1.1
[25] sass_0.3.0   

SigurdJanson added a commit to SigurdJanson/Fate-Explorer.R that referenced this issue Jan 30, 2021
@wch
Copy link
Collaborator

wch commented Feb 1, 2021

@SigurdJanson Thanks for that example. This is a difficult (or really, almost impossible) problem to fix in general, because of R's nature as a loosely-typed language.

The root issue is that jsonlite doesn't like named atomic vectors when keep_vec_names=TRUE:

> jsonlite::toJSON(c(a=1), keep_vec_names=TRUE)
Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.
{"a":1} 

In contrast, named lists are fine:

> jsonlite::toJSON(list(a=1), keep_vec_names = TRUE)
{"a":[1]} 

In the examples posted previously, it seems that something in ggplot2 generated data with named atomic vectors. In @SigurdJanson's example, it's the call to updateSliderInput() that tries to send a named vector.

In Shiny, we do some input validation, we don't check every possible input for every possible kind of invalid value. (It's similar to the vast majority of R code in this way.) With a strongly-typed language, many checks just happen automatically; with a loosely-typed language like R, deciding which things to check (and whether to "fix" them for the user) is much more subjective.

@lbramley
Copy link

lbramley commented May 4, 2023

Is there any option for a workaround here? This issue is making it impossible to label graphs other than using a legend. The functions ggrepel::geom_label_repel and ggplot2::geom_label also seem to throw the same error once reactive inputs are used.

library(ggplot2)
library(ggrepel)
library(shiny)

# Define UI 
ui <- fluidPage(

    # Application title
    titlePanel("mtcars plot"),

    # Sidebar with a slider input for minimum displacement
    sidebarLayout(
        sidebarPanel(
            sliderInput("disp",
                        "Minimum Displacement (cu.in.):",
                        min = 70,
                        max = 470,
                        value = 70)
        ),

        # Show the resulting plot
        mainPanel(
           plotOutput("mtcars_plot")
        )
    )
)

# Define server logic required to draw the mtcars plot
server <- function(input, output) {

    output$mtcars_plot <- renderPlot({
        mtcars_disp <- mtcars %>%
            filter(disp >= input$disp)
        
        p <- ggplot(mtcars_disp,
                    aes(wt, mpg, label = rownames(mtcars), colour = factor(cyl))) +
            geom_point()
        
        # Labels with background
        p + geom_label() # or geom_label_repel()
        
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

@gadenbuie
Copy link
Member

Hi @lbramley, I just tried your app and can reproduce the error. There's a rather long message that's printed, for me it's the following:

Warning: ggrepel: 2 unlabeled data points (too many overlaps). Consider increasing max.overlaps
Warning: Error in geom_point: Problem while computing aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error in `check_aesthetics()`:
! Aesthetics must be either length 1 or the same as the data (16)
✖ Fix the following mappings: `label`
  198: <Anonymous>
  197: signalCondition
  196: signal_abort
  195: rlang::abort
  194: cli::cli_abort
  193: handlers[[1L]]
  192: <Anonymous>
  191: signalCondition
  190: signal_abort
  189: rlang::abort
  188: cli::cli_abort
  187: check_aesthetics
  186: compute_aesthetics
  185: l$compute_aesthetics
  184: f
  177: by_layer
  176: ggplot_build.ggplot
  174: print.ggplot
  169: func
  167: f
  166: Reduce
  157: do
  156: hybrid_chain
  128: drawPlot
  114: <reactive:plotObj>
   98: drawReactive
   85: renderFunc
   84: output$mtcars_plot
    3: runApp
    2: print.shiny.appobj
    1: <Anonymous>
Input to asJSON(keep_vec_names=TRUE) is a named vector. In a future version of jsonlite, this option will not be supported, and named vectors will be translated into arrays instead of objects. If you want JSON object output, please use a named list instead. See ?toJSON.
Run `rlang::last_trace()` to see where the error occurred.

That second-to-last line about asJSON() is really a misdirection; that's a jsonlite error that happens after other errors occur. In this case the key lines are

Warning: Error in geom_point: Problem while computing aesthetics.
ℹ Error occurred in the 1st layer.
Caused by error in `check_aesthetics()`:
! Aesthetics must be either length 1 or the same as the data (16)
✖ Fix the following mappings: `label`

which occur because you need to use the same data frame for label as is provided to ggplot():

p <- ggplot(mtcars_disp,
-	aes(wt, mpg, label = rownames(mtcars), colour = factor(cyl))) +
+	aes(wt, mpg, label = rownames(mtcars_disp), colour = factor(cyl))) +
	geom_point()

@lbramley
Copy link

lbramley commented May 9, 2023

Thanks @gadenbuie! Really helpful to know that the asJSON() error is a misdirection; my real app is using the same object unlike the test one above, but it must be something in my code then, sorry about that!

@jcheng5
Copy link
Member

jcheng5 commented May 9, 2023

@gadenbuie Is the asJSON error happening when attempting to JSON-serialize a fancy rlang error? I have a vague feeling like those fancy errors need to be accounted for in Shiny's catch-error-during-output-render logic.

@gadenbuie
Copy link
Member

gadenbuie commented May 10, 2023

Is the asJSON error happening when attempting to JSON-serialize a fancy rlang error?

@jcheng5 Maybe? That also feels likely to me too, although it doesn't seem to be going through shiny's internal toJSON() and I'm getting lost in the many error handlers. Do you have any suggestions about where to look for the error-to-JSON serialization?

@toxintoxin
Copy link

I also get a warning when renderPlot, but if I activate the shiny from R not radian, everything goes well

@olivroy
Copy link
Contributor

olivroy commented Dec 11, 2024

Just saw this while trying to debug some code. See #4167 for a reprex if it helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests