Able to run shiny app in command window but unable to run using runApp() function

I'm building a multifile shiny app to create a simple dashboard with a scatter plot, bar chart, and leaflet map. When running "shinyApp(ui = ui, server = server)" I'm able to use my app with full functionality. When clicking the Run App button or executing runApp() function I get the following error:
Error in serverFuncSource() :
server.R returned an object of unexpected type: list

I've been unable to identify where the list within the server function is being generated and have had little luck finding a good explanation for what might be causing this error. I've attached the server function below in hopes of getting an explanation of what causes this error and where it exists in this code. My suspicion is that I'm misunderstanding something to do with reactive funtions or perhaps the fact that the data is being loaded from a different folder? Thank you for any help you can lend.

# Define server logic #####################
server <- function(input, output, session) {
    
    # Reactive Expressions
    filtered_data <- reactive({
        req(input$organizationname)  # Require the input to be available
        master.table %>%
            filter(organizationname == input$organizationname)
    })
    
    column_range <- reactive({
        enrollment <- filtered_data()[["enrollment"]]
        range(enrollment, na.rm = TRUE)
    })
    
    # Render leaflet map
    output$map <- renderLeaflet({
        if (nrow(filtered_data()) > 0) {
            leaflet() %>%
                addTiles() %>%
                setView(lng = -95.7129, lat = 37.0902, zoom = 4) %>%
                addMarkers(data = filtered_data(), 
                    lng = ~lng, lat = ~lat,
                    popup = ~paste("Organization:", filtered_data()$organizationname, "<br>",
                        "Plan Name:", filtered_data()$planname, "<br>",
                        "Enrollment:", filtered_data()$enrollment, "<br>",
                        "Premium:", filtered_data()$premium))
        } else {
            return(NULL)  # Return NULL explicitly if no data is available
        }
    })
    
    # Render bar plot
    output$bar <- renderPlot({
        if (nrow(filtered_data()) > 0) {
            ggplot(filtered_data(), aes(x = bin, y = enrollment)) +
                geom_bar(stat = "identity", fill = "skyblue") +
                labs(title = paste("Enrollment for Competitor", input$organizationname),
                    x = "Premium", y = "Enrollment") +
            scale_y_continuous(labels = scales::comma_format())
        } else {
            return(NULL)  # Return NULL explicitly if no data is available
        }
    })
    
    # Render scatter plot
    output$scatter <- renderPlot({
        if (nrow(filtered_data()) > 0) {
            ggplot(filtered_data(), aes(x = premium, y = enrollment)) +
                geom_point() +
                labs(title = paste("Enrollment for Competitor", input$organizationname),
                    x = "Premium", y = "Enrollment") +
                scale_y_continuous(limits = column_range(),  # Specify the range of Y axis
                    labels = scales::comma_format())
        } else {
            return(NULL)  # Return NULL explicitly if no data is available
        }
    })
}

More information would be helpful.

  • Does your application directory contain files named ui.R and server.R? If not, what (relevant) files does it contain?

  • Is the code in your question the server.R (or equivalent) file?

  • Can you post the ui.R file?

  • When you try runApp(), what arguments do you plug in?

  • Is your working directory the application code directory when you run it?

Thank you for your time and consideration!

  1. Yes, the file currently contains ui.r, server.r, and an rsconnect folder to host it to shiny.io. I have longer-term goals adding different features and data exhibits but this is all the progress I've made.
  2. Yes. There is some data loading and cleaning to generate an object "master.table" above the server function, but I didn't initially suspect the problem is related to that as I can run the app successfully with "shinyApp(ui = ui, server = server)"
  3. Yes, ui.r code is posted below.
  4. I don't plug any argument in, when I use the Run App button in the source/scripting window the first line displays as runApp() so I've assumed that's the function the button performs. Are there arguments that should be appearing here?
  5. Yes.

I initially set out on this project to teach myself the basics of creating a dashboard and hosting it online with the future intent to add more features. Would consolidating this into a single app.r file potentially resolve this issue? At this point I just want to be able to access my app through a browser.

UI CODE:

library(shiny)

# Define UI for application that draws a histogram
ui <- fluidPage(

    # Application title
    titlePanel("MA Carriers and Plans"),
    
    # Sidebar with a slider input for number of bins
    sidebarLayout(
        sidebarPanel(
            selectInput(
                "organizationname",
                "Organization",
                choices = unique(master.table$organizationname)
            )
        ),
        mainPanel(
            # Include Scatter and Bar chart in main panel
            plotOutput("bar"),
            plotOutput("scatter"),
            
            # Show a leaflet map of selected carrier
            leafletOutput("map")
        )
        )
    )

runApp() has default values for all arguments, including the working directory as the default for the application directory. So if you invoke it while the app directory is the working directory, you do not need to supply any arguments.

Your R files both refer to a data frame (?) named master.table which does not seem to be defined anywhere, and they invoke functions such as leaflet that I assume come from library packages not mentioned in the code. That means the rest of us on the list cannot test the code. Make sure your app does not assume that there will be libraries loaded or data objects in memory other than those it loads/creates itself.

Thank you for talking me through all of this!

I was finally able to resolve the issue by consolidating code into a single-file app in a new directory. As far as I can tell there's something I don't fully understand with a multifile app that will likely take some additional work in the future to understand. For reference I've linked the dashboard I've now been able to publish and attached my single file app code below.

https://kobe-cornelison.shinyapps.io/Demo_Dashboard/

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(readr)
library(tidyverse)
library(dplyr)
library(maps)
library(leaflet)
library(leaflegend)
library(leaflet.extras)
library(mapview)
library(sp)
library(ggplot2)
library(shiny)
library(shinydashboard)
library(httr)
library(rsconnect)

# Load Data Sets for analysis - CMS data, geographic data
MA_Contract_directory_2024_03 <- read_csv("MA_Contract_directory_2024_03.csv")
PDP_Contract_directory_2024_03 <- read_csv("PDP_Contract_directory_2024_03.csv")
MA_Landscape_2023 <- read_csv("ma2023.csv")
PDP_Landscape_2023 <- read_csv("pdp2023.csv")
uscities <- read.csv("uscities.csv")
Monthly_Report_By_Plan_2024_03 <- read.csv("Monthly_Report_By_Plan_2024_03.csv")

# DATA CLEANING ##############################################
colnames(MA_Landscape_2023)[colnames(MA_Landscape_2023) == "contractid"] <- "contractnumber"  #Makes contract number header same between data sets
colnames(MA_Contract_directory_2024_03)[colnames(MA_Contract_directory_2024_03) == "Contract Number"] <- "contractnumber"
colnames(PDP_Landscape_2023)[colnames(PDP_Landscape_2023) == "contractid"] <- "contractnumber"  #Makes contract number header same between data sets
colnames(PDP_Contract_directory_2024_03)[colnames(PDP_Contract_directory_2024_03) == "Contract Number"] <- "contractnumber"

county.city <- uscities %>%  #Largest city in each county to be used for leaflet marker placement
    group_by(state_name, county_name) %>%
    filter(rank(desc(population)) == 1) %>%
    ungroup()
colnames(county.city)[colnames(county.city) == "county_name"] <- "county"

MA_Contract_directory_2024_03$Enrollment <- gsub(",", "", MA_Contract_directory_2024_03$Enrollment) %>% # remove commas from enrollment column, convert numeric
    as.numeric(MA_Contract_directory_2024_03$Enrollment, na.rm = TRUE) 

MA_Landscape_2023$contractnumplanid <- paste0(MA_Landscape_2023$contractnumber, MA_Landscape_2023$planid) #concatenate contract number and plan id
Monthly_Report_By_Plan_2024_03$contractnumplanid <- paste0(Monthly_Report_By_Plan_2024_03$Contract.Number, Monthly_Report_By_Plan_2024_03$Plan.ID) #concatenate contract number and plan id

# DATA CONSOLIDATION #########################################

master.table <- merge(Monthly_Report_By_Plan_2024_03, MA_Landscape_2023, by = "contractnumplanid")  #combine Directory, Landscape and geography data frames
master.table$contractnumplanid <- paste0(master.table$contractnumber, master.table$planid) #concatenate contract number and plan id
master.table <- merge(master.table, county.city, by = "county")                # add lat and long to master tables



#select desired columns for analysis
master.table <- data.frame(         
    state = master.table$state,
    county = master.table$county,
    city = master.table$city,
    lng = master.table$lng,
    lat = master.table$lat,
    parentorg = master.table$`Parent.Organization`,
    organizationname = master.table$organizationname,
    contractnumber = master.table$contractnumber,
    planid = master.table$planid,
    contractnumplanid = master.table$contractnumplanid,
    planname = master.table$planname,
    plantype = master.table$`Plan.Type`,
    enrollment = as.numeric(master.table$Enrollment),
    premium = as.numeric(master.table$monthlyconsolidatedpremiumi),
    deductible = as.numeric(master.table$annualdrugdeductible))

master.table <- master.table[!duplicated(master.table$contractnumplanid), ]#eliminate duplicates
master.table <- na.omit(master.table)  


premium.bins <- c(0,1,25,50,100,149,Inf ) #add premium bins for histogram
premium.bins.labs <- c("$0", "$1-24", "$25-49", "$50-99", "$100-149", "$150+")
master.table$bin <- cut(master.table$premium, breaks = premium.bins, labels = premium.bins.labs, include.lowest = TRUE)

# Generate values for plots ###################################
#National Summary
MA.nat.plancount <- n_distinct(master.table$contractnumber)# MA BLOCK ##########
MA.nat.carriercount <- n_distinct(master.table$parentorg)
MA.nat.enrollment <- gsub(",", "", MA_Contract_directory_2024_03$Enrollment) # remove commas from enrollment column, convert numeric
MA.nat.enrollment <- as.numeric(MA.nat.enrollment)
MA.nat.enrollment <- sum(MA.nat.enrollment, na.rm = TRUE)


# Define UI for application that draws a histogram
ui <- fluidPage(
    
    # Application title
    titlePanel("MA Carriers and Plans"),
    
    # Sidebar with a slider input for number of bins
    sidebarLayout(
        sidebarPanel(
            selectInput(
                "organizationname",
                "Organization",
                choices = unique(master.table$organizationname)
            )
        ),
        mainPanel(
            # Include Scatter and Bar chart in main panel
            plotOutput("bar"),
            plotOutput("scatter"),
            
            # Show a leaflet map of selected carrier
            leafletOutput("map")
        )
    )
)

# Define server logic required to draw a histogram
server <- function(input, output, session) {
    
    # Reactive Expressions
    filtered_data <- reactive({
        req(input$organizationname)  # Require the input to be available
        master.table %>%
            filter(organizationname == input$organizationname)
    })
    
    column_range <- reactive({
        enrollment <- filtered_data()[["enrollment"]]
        range(enrollment, na.rm = TRUE)
    })
    
    # Render leaflet map
    output$map <- renderLeaflet({
        if (nrow(filtered_data()) > 0) {
            leaflet() %>%
                addTiles() %>%
                setView(lng = -95.7129, lat = 37.0902, zoom = 4) %>%
                addMarkers(data = filtered_data(), 
                    lng = ~lng, lat = ~lat,
                    popup = ~paste("Organization:", filtered_data()$organizationname, "<br>",
                        "Plan Name:", filtered_data()$planname, "<br>",
                        "Enrollment:", filtered_data()$enrollment, "<br>",
                        "Premium:", filtered_data()$premium))
        } else {
            return(NULL)  # Return NULL explicitly if no data is available
        }
    })
    
    # Render bar plot
    output$bar <- renderPlot({
        if (nrow(filtered_data()) > 0) {
            ggplot(filtered_data(), aes(x = bin, y = enrollment)) +
                geom_bar(stat = "identity", fill = "skyblue") +
                labs(title = paste("Enrollment by Premium Bin", input$organizationname),
                    x = "Premium", y = "Enrollment") +
                scale_y_continuous(labels = scales::comma_format())
        } else {
            return(NULL)  # Return NULL explicitly if no data is available
        }
    })
    
    # Render scatter plot
    output$scatter <- renderPlot({
        if (nrow(filtered_data()) > 0) {
            ggplot(filtered_data(), aes(x = premium, y = enrollment)) +
                geom_point() +
                labs(title = paste("Plans by Premium & Enrollment", input$organizationname),
                    x = "Premium", y = "Enrollment") +
                scale_y_continuous(limits = column_range(),  # Specify the range of Y axis
                    labels = scales::comma_format())
        } else {
            return(NULL)  # Return NULL explicitly if no data is available
        }
    })
}

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

I suspect your issue with the two file approach has to do with creating variables in the global environment, which you do in the single file version (the code between the library statements and the ui <- ... line). Both ui and server are functions, and any variables created within them are local to them.

In the single file version, you create master.table in the global environment, which is visible inside both ui and server. In the two file version, if you refer to master.table inside both ui and server, those are actually two different tables.

One last tip: if you want to create a variable inside a function but have it globally visible, use <<- rather than <-.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.