Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Debug when the Line Number of Error is not Provided?

Tags:

I am using shiny and shinydashboard to create a dashboard. The minimum example codes are as below:

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
    dashboardHeader(title = "test"),
    dashboardSidebar(
        sidebarMenu(
            menuItem(text = "Tab One",tabName = "tab1"),
            menuItem(text = "Tab Two",tabName = "tab2"),
            id = "sidebar"), # an extra comma here!
    ),
    dashboardBody()
)


server <- function(input,output){}


shinyApp(ui,server)

When I run this App, there is an error message:

Error in tag("section", list(...)) : argument is missing, with no default

I know I got this error because I have an extra comma at the end of line 10. But the problem is that:

I have a similar error in my app, but the app contains more than 20 different R files sourcing each other and more than 2000 lines of code. It's impossible for me to go over each file and try to spot where I put an extra comma.

My question is:

Is there an easier way to let R print error message with line number and file source? Or is there a better way to debug this kind of errors where no detail is provided? Thanks!


Ideally, I want the error message to be something similar to this:

Error in source: <folder>/<file.R> 9:10: argument is missing, with no default
9:      menuItem(text = "Tab Two",tabName = "tab2"),
10:     id = "sidebar"), # an extra comma here!
                       ^
like image 409
yusuzech Avatar asked May 03 '19 19:05

yusuzech


2 Answers

Source the main file rather than running it, and after the error happens run

traceback()

in the console. When I do that with your simple example, I see this:

> traceback()
11: tag("section", list(...))
10: tags$section(id = "sidebarItemExpanded", class = "sidebar", `data-disable` = if (disable) 1 else NULL, 
        list(...))
9: tag("aside", list(...))
8: tags$aside(id = "sidebarCollapsed", class = "main-sidebar", `data-collapsed` = dataValueString, 
       custom_css, tags$section(id = "sidebarItemExpanded", class = "sidebar", 
           `data-disable` = if (disable) 1 else NULL, list(...)))
7: dashboardSidebar(sidebarMenu(menuItem(text = "Tab One", tabName = "tab1"), 
       menuItem(text = "Tab Two", tabName = "tab2"), id = "sidebar"), 
       )
6: tagAssert(sidebar, type = "aside", class = "main-sidebar")
5: dashboardPage(dashboardHeader(title = "test"), dashboardSidebar(sidebarMenu(menuItem(text = "Tab One", 
       tabName = "tab1"), menuItem(text = "Tab Two", tabName = "tab2"), 
       id = "sidebar"), ), dashboardBody()) at .active-rstudio-document#4
4: eval(ei, envir)
3: eval(ei, envir)
2: withVisible(eval(ei, envir))
1: source("~/.active-rstudio-document", echo = TRUE)

Notice that the expression labelled 5: has line number information: .active-rstudio-document#4. That's the file RStudio saved before sourcing, and the #4 part says the issue is on line 4. Line 4 is the big call to dashboardPage. You're not going to get any finer detail than that unless you break up your code into smaller expressions. This will feel really unnatural, and hopefully won't be necessary, but you could write the original as

library(shiny)
library(shinydashboard)

header <- dashboardHeader(title = "test")
sidebar <- dashboardSidebar(
  sidebarMenu(
    menuItem(text = "Tab One",tabName = "tab1"),
    menuItem(text = "Tab Two",tabName = "tab2"),
    id = "sidebar"), # an extra comma here!
)
body <- dashboardBody()
ui <- dashboardPage(
  header,
  sidebar,
  body
)

server <- function(input,output){}

shinyApp(ui,server)

When I do that, the traceback() includes this line:

5: dashboardSidebar(sidebarMenu(menuItem(text = "Tab One", tabName = "tab1"), 
       menuItem(text = "Tab Two", tabName = "tab2"), id = "sidebar"), 
       ) at .active-rstudio-document#5

which tells me where the problem came from.

Edited to add: Another way to see the traceback is to run

options(error = recover)

before sourcing everything. The run will die with a display like the traceback() display, but formatted differently. It also lets you examine variables in each of the evaluation frames, which probably isn't helpful in this example, but sometimes is very helpful.

like image 188
user2554330 Avatar answered Oct 14 '22 09:10

user2554330


You could use source() instead:

(For an example i modified your code by putting the ui with error in an extra file uiFile.R.

enter image description here

and then active the traceback (see the right part of the picture: Show Traceback).

Then you will see:

enter image description here

It is not optimal as it doesnt show you line 10, but you can at least click the blue highlighted output and navigate to the error.

For more techniques on how to debug shiny apps this page is very helpful: https://shiny.rstudio.com/articles/debugging.html.

like image 38
Tonio Liebrand Avatar answered Oct 14 '22 07:10

Tonio Liebrand