Error while publishing R Shiny App

I am pretty new to coding in R and am attempting to publish a quiz I coded as an R Shiny app, but am getting this error message
"
Warning: Error in [.data.frame: object 'single_cat' not found
76: [.data.frame
73: validate_cat [C:\Users\taylo\OneDrive\Documents\quizz/app.R#48]
72: observeEventHandler [C:\Users\taylo\OneDrive\Documents\quizz/app.R#160]
1: runApp
"
This is the code I have
'ui <- fluidPage(

#creates a set of radio buttons, only one of which can be pressed at any time
#id: rand_or_spec-what i refer to it as and its stored as computationally, label is radio buttons with h3-hierarchical difference for formatting
#choices: a list of values, widget will build a button for each value of the list. text/value LIKE key/value. text shows up, value is whats stored as computationally
#selected: value that should be initially selected
radioButtons("rand_or_spec", label = h3("Radio buttons"),
             choices = list("Random Category" = 1, "Specific Category" = 2), 
             selected = NULL), 
#placeholder from when server going to plug in text box
uiOutput("Specific_Category"),
#creates action button for submitting users choice, either random or what they enter
actionButton("submit_category", label = "SUBMIT"),
#area that prints what the category is after they have been selected
uiOutput("category_selected"),
#placeholder for when server puts in questions into text boxes for all 5 questions (cont'd) 
#and text box for user to answer questions
uiOutput("quiz"),
#printing # correct
uiOutput("number_correct")

)
#creates server function, which is where the output is generated, some of which are puts of the ui.
#server is listener.input is clicked, output is generated
#render is action button to take stuff from server and render it to ui
#can put server in seperate file in ui
server <- function(input, output){
validate_cat <- function (cat){
if (nrow(jeop3column[jeop3column$category == cat,]) >= 5){
return(cat)
}
else{
new_cat <- sample(unique(as.character(jeop3column$category)), 1)
validate_cat(new_cat)
}
}
#imports jeop3column dataframe from csv
jeop3column <- read.csv(file = "data/jeop3column2.csv")
#observes aka if ANY of the inputs referenced that are mentioned in observe function changes, code in the observe runs again: if specific_category is chosen, render Specific_Category
#creates new textinput button with ID of user_category, without a label, that says "input category here"
#or else, BREAK -> go to next section
observe({
if(input$rand_or_spec == 2){
output$Specific_Category <- renderUI({
#taglist makes output get one html element, computationally known as "user_category", no label, text
tagList(textInput("user_category", label = NULL, value = "input category here"))

        })
    }
    else{
        output$Specific_Category <- renderUI({
            br()
        })
    }
})

#next observe the event that if/WHEN the submit category button is clicked, then following code will be run
#create a variable called single category that is a random selection of 
#a category from my df. 
#sample is a function for a random selection, 1 = sample size, [[1]] == get a string and not list
single_cat_gen <- 'b0o'
observeEvent(input$submit_category, {
    if(input$rand_or_spec == 1){
        
        single_cat <- sample(unique(as.character(jeop3column$category)), 1)
        
        #if not random, single_cat = user input for user category   
    } else{
        #if what user entered in cateogry, uses that, DO MORE FUZZY WUZZY
        if (input$user_category %in% jeop3column$category)
            single_cat <- input$user_category
        else
            single_cat <- sample(unique(as.character(jeop3column$category)), 1)[[1]]
    }
    #single_cat_df == subset of jeop3column where category == selected single category
    #single_cat with 5 questions == sample of scdf with 5 selections of rows, all the columns
    
    
    
    #function for validating category
    #if number of rows in dataframe where category is category >=5, category is ok
    #or else new category = a new random sample from df, then repeat >=5
    validate_cat <- function (cat){
        if (nrow(jeop3column[jeop3column$category == cat,]) >= 5){
            print(cat)
            return(cat)
        }
        else{
            new_cat <- sample(unique(as.character(jeop3column$category)), 1)
            validate_cat(new_cat)
        }
    }
    
    #single category being selected
    single_cat <- validate_cat(single_cat)
    single_cat_df <- jeop3column[jeop3column$category == single_cat, ]
    single_cat_df_5 <- single_cat_df[sample(nrow(single_cat_df), 5), ]
    single_cat_gen <- single_cat_df_5
    #observe when category is created and create displayed category button
    
    output$category_selected <- renderUI({
        paste("Category Selected: ", single_cat)
        
    })
    
    #output of quiz
    #what does tag list do
    #creates text input, label is question, then populates 1st q from df, enter text for answer 
    #paste joins two strings in r: question 1 AND question from DF  
    
    output$quiz <- renderUI({
        tagList(
            textInput("answer1", label = h3(paste("QUESTION 1: ", single_cat_gen$answer[1])), value = "Enter text..."),
            textInput("answer2", label = h3(paste("QUESTION 2: ", single_cat_gen$answer[2])), value = "Enter text..."),
            textInput("answer3", label = h3(paste("QUESTION 3: ", single_cat_gen$answer[3])), value = "Enter text..."),
            textInput("answer4", label = h3(paste("QUESTION 4: ", single_cat_gen$answer[4])), value = "Enter text..."),
            textInput("answer5", label = h3(paste("QUESTION 5: ", single_cat_gen$answer[5])), value = "Enter text..."),
            actionButton("submit_answers", label = "Submit Answers")
        )
    })
})


# s1 = input$answer1
# s2 = single_cat_df_5$question[1]
# init = FuzzMatcher$new()
# init$Ratio(string1 = s1, string2 = s2)
# init$Partial_ratio(string1 = s1, string2 = s2)
# init$Token_sort_ratio(string1 = s1, string2 = s2, force_ascii = TRUE, full_process = TRUE)
# init$Token_set_ratio(string1 = s1, string2 = s2, force_ascii = TRUE, full_process = TRUE)
# 
# s1
# init$Ratio

observeEvent(input$submit_answers, {
    num_right <- 0
    
   
    
    #single category being selected
    single_cat <- validate_cat(single_cat)
    single_cat_df <- jeop3column[jeop3column$category == single_cat, ]
    single_cat_df_5 <- single_cat_df[sample(nrow(single_cat_df), 5), ]
    
    
    if (input$answer1 == single_cat_df_5$question[1])
        num_right <- num_right + 1
    if (input$answer2 == single_cat_df_5$question[2])
        num_right <- num_right + 1
    if (input$answer3 == single_cat_df_5$question[3])
        num_right <- num_right + 1
    if (input$answer4 == single_cat_df_5$question[4])
        num_right <- num_right + 1
    if (input$answer5 == single_cat_df_5$question[5])
        num_right <- num_right + 1
    
    output$number_correct <- renderUI({
        paste("Percentage correct", "YOU GOT A: ", num_right)
    })
})


# add a submit answer button in taglist
# when clicked
# get user answers, match dataframe, print # correct, which render

}

shinyApp(ui = ui, server = server)
'

I am so new to coding and troubleshooting I'm not sure where to start.

Anyone know how I can find the single_cat that is not defined?

If so please let me know, I'm new to coding and could use the help.

Thanks,

-Taylor