2

I'm working on an upload/download function in R Shiny for saving and retrieving user inputs into data frames and other table objects. Files are locally saved to the user machine. I'm using tryCatch() for error handling but I find myself having to be very specific in the types of upload errors to look for, such as column/row mismatches, file type (.RDS) mismatches, and data type mismatches. This is onerous and I'm probably missing other things in an an upload attempt that could crash the code. Is there a way to simply ignore an upload if it would otherwise crash the code for any reasons?

I show code excerpts below only. Let me know if I should instead post a complete working example.

Here is my onerous observer for looking out for the 3 types of crash causes:

# Handle the uploaded file from modal
  observeEvent(input$file_upload, {
    req(input$file_upload)
    
    tryCatch({
      uploaded_data <- readRDS(input$file_upload$datapath)
      
      # Check if the uploaded data is a dataframe
      if (!is.data.frame(uploaded_data)) {
        stop("Upload target file is of incorrect type. Try again")
      }
      
      # Get the expected dataframe structure from user_input()
      expected_data <- user_input()
      
      # Check if the dimensions match
      expected_cols <- ncol(expected_data)
      expected_rows <- nrow(expected_data)
      
      if (ncol(uploaded_data) != expected_cols || nrow(uploaded_data) != expected_rows) {
        stop("Upload target file is of incorrect type. Try again")
      }
      
      # Check if the data types of each column match
      for (i in seq_len(expected_cols)) {
        # Get the class (data type) of each column in expected_data and uploaded_data
        expected_type <- class(expected_data[[i]])
        uploaded_type <- class(uploaded_data[[i]])
        
        # If data types don't match, raise an error
        if (expected_type != uploaded_type) {
          stop("Upload target file is of incorrect type. Try again.")
        }
      }
      
      # If everything is fine, update the reactive dataframe and close modal
      user_input(uploaded_data)
      removeModal()  # Close the modal
      
    }, error = function(e) {
      # If an error occurs, show a notification and return NULL
      showNotification("Upload target file is of incorrect type. Try again.", type = "error", duration = 5)
      return(NULL)
    })
  })

And here is the observer without any sort of upload filtering:

 observeEvent(input$file_upload_modal, {
    req(input$file_upload_modal)
    uploaded_data <- readRDS(input$file_upload_modal$datapath)
    user_input(uploaded_data)  # Update the reactive user input dataframe
    removeModal()  # Close the modal once the file is uploaded
  })
7
  • 3
    Welcome to real world programming. Users do stupid things. If you don't want your app to crash because of what they do, you'll probably need to put more effort into stopping them from doing what you don't want than helping them do what you do want. You can, however, improve the readability of your observer (and other parts of the main program logic) by delegating error checking to helper functions. So, rather than readRDS(input$file_upload_modal$datapath), you could uploaded_data <- getValidDataOrNULL(input$file_upload_modal$datapath). Commented Sep 17, 2024 at 11:23
  • 3
    Thanks Limey. I would be a much better code crash tester than programmer. I know how to crash code. I do stupid well. I've had incidence reports filed with big banks when I found errors in their website processing. One even put me in direct touch with their IT as if I was an employee and not a customer to help them fix it. Commented Sep 17, 2024 at 11:38
  • 1
    @Limey Other web frameworks have catch-all clauses that you can use to prevent any input error to crash the application. Pretty sure that that’s what OP is after. Maybe globalCallingHandlers() could be used to achieve this for Shiny. Otherwise, maybe getOption('error')`, although I think at that point it might be too late to prevent unwinding. Commented Sep 17, 2024 at 11:47
  • 2
    Just FYI: As of shiny 1.8.1 there is the possibility to register a callback function via onUnhandledError(). This handler doesn't stop the error or prevent the session from closing, but it can be used to log the error [source]. Commented Sep 17, 2024 at 12:24
  • 1
    @KonradRudolph. I agree. However, I suspect end users don't want a generic "something went wrong" message. I (they) want to know speficis, together with advice on how to put things right. That means anticipating errors and providing customised feedback. That takes time and effort. Which was point I was trying to make. Commented Sep 17, 2024 at 12:28

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.