SSL certificate problem: certificate has expired for api.plot.ly

Hello,

I have been trying to generate a plotly image into a pdf with some user reponses in a R shiny app. But I am getting an error:

Error in curl::curl_fetch_disk(url, x$path, handle = handle): SSL peer certificate or SSH remote key was not OK [api.plot.ly]: SSL certificate problem: certificate has expired

Here is a reproducible example:

library(plotly)
library(knitr)
library(webshot)
library(shiny)


ui =
  
  
  fluidPage(
    tabPanel("EisenVerla",
             tabsetPanel(id = "Eisen_subtabs",
                         tabPanel("Self_Assessment",
                                  fluidRow(
                                    column(
                                      width = 7,
                                      div(
                                        style = "border: 1px solid #dddddd; padding: 10px; margin-bottom: 20px",
                                        tags$h4("selfAssesment", style = "text-align: left; font-weight: bold; margin-bottom: 20px;"),
                                        
                                        # Questions with consistent spacing
                                        div(
                                          style = "margin-top: 20px;",  # Added margin for alignment with criteria
                                          
                                          # 1
                                          div(
                                            tags$h5("Enter your response"),
                                            radioButtons("response1", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
                                            textAreaInput("response_text1", label = "Comment", placeholder = "Enter text...")
                                          ),
                                          # 2
                                          div(
                                            tags$h5("Enter your response"),
                                            radioButtons("response2", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
                                            textAreaInput("response_text2", label = "Comment", placeholder = "Enter text...")
                                          ),
                                          
                                          # 3
                                          div(
                                            tags$h5("Enter your response"),
                                            radioButtons("response3", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
                                            textAreaInput("response_text3", label = "Comment", placeholder = "Enter text...")
                                          ),
                                          
                                          # 4
                                          div(
                                            tags$h5("Enter your response"),
                                            radioButtons("response4", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
                                            textAreaInput("response_text4", label = "Comment", placeholder = "Enter text...")
                                          ),
                                          
                                          # 5
                                          div(
                                            tags$h5("Enter your response"),
                                            radioButtons("response5", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
                                            textAreaInput("response_text5", label = "Comment", placeholder = "Enter text...")
                                          ),
                                          
                                          # 6
                                          div(
                                            tags$h5("Enter your response"),
                                            radioButtons("response6", label = NULL, choices = c("N/A", 1:5), selected = "N/A", inline = TRUE),
                                            textAreaInput("response_text6", label = "Comment", placeholder = "Enter text...")
                                          )
                                        )
                                      )
                                    ),
                                    column(
                                      width = 2,
                                      fluidRow(
                                        column(4,
                                               div(align = "left",
                                                   actionButton("export", "Export Plot"),
                                                   plotlyOutput("plot_example_1", width = "800px", height = "550px"),
                                                   downloadButton("downloadPlot", "Download Plot (PNG)"),
                                                   style = "margin-right: 500px;"
                                               ),
                                               downloadButton("dnld", "Download PDF Report")
                                        )
                                      )
                                    )
                                  ),
                                  
                                  mainPanel()
                         )
             )
    )
  )
  
server <- function(input, output, session) {
  
  # Compute numeric values for plot inside a reactive expression
  numeric_values <- reactive({
    sapply(1:6, function(i) {
      val <- input[[paste0("response", i)]]
      if (is.null(val) || is.na(val)) NA_real_ else as.numeric(val)
    })
  })
  
  # interactive Plotly plot from user-based response
  plot_function <- reactive({
    plot_ly(
      mode = 'markers+lines',
      type = 'scatterpolar',
      fill = 'toself',
      fillcolor = "rgba(231, 184, 0, 0.5)",
      line = list(color = 'rgb(0, 0, 0)'),
      marker = list(
        symbol = 100,
        size = 6,
        color = 'rgb(0, 0, 0)',
        line = list(color = 'rgb(0, 0, 0)', width = 1)
      ),
      r = numeric_values(),  # Use the reactive numeric_values()
      theta = c("<b>1</b>", "<b>2</b>", "<b>3</b>", "<b>4</b>", "<b>5</b>", "<b>6</b>")
    ) |>
      layout(
        title = list(text = "Self_Assessment", y = 0.99),
        polar = list(radialaxis = list(visible = TRUE, range = c(0, 5))),
        angularaxis = list(rotation = 90, direction = "clockwise"),
        showlegend = FALSE,
        margin = list(l = 30, r = 30, b = 30, t = 30),
        font = list(size = 9, color = 'black'),
        paper_bgcolor = "#B4D9F9",
        plot_bgcolor = "#B4D9F9",
        width = 400,
        height = 300
      )
  })
  
  output$plot_example_1 <- renderPlotly({
    plot_function()
  })
  
  
  # getting user responses
  # Combine numeric and text responses into a data frame
  user_responses <- reactive({
    data.frame(
      Question = 1:6,
      Numeric_Response = sapply(1:6, function(i) {
        input[[paste0("response", i)]]
      }),
      Text_Response = sapply(1:6, function(i) {
        input[[paste0("response_text", i)]]
      }),
      stringsAsFactors = FALSE
    )
  })
  
  # download
    output$dnld <- downloadHandler(
    filename = "report.pdf",
    content = function(file) {


      # Save the Plotly chart as a PNG file
      plotly_IMAGE(plot_function(), format = "png", out_file = "plot_example_1.png")

     
      #orca(plot_function(),"plot_example_1.png")


      # Path to the LaTeX template
      src <- normalizePath('report.Rnw')

      # Temporarily switch to the temp directory
      owd <- setwd(tempdir())
      on.exit(setwd(owd))
      file.copy(src, 'report.Rnw', overwrite = TRUE)

      # Save the user responses into a temporary file for LaTeX
      write.table(
        user_responses(),
        file = "user_responses.csv",
        sep = ",",
        row.names = FALSE,
        col.names = TRUE
      )


      # Knit the LaTeX document to PDF
      out <- knitr::knit2pdf('report.Rnw', clean = TRUE)
      file.rename(out, file)
    }
  )
}

shinyApp(ui, server)

report.Rnw

\documentclass[10pt,a4paper]{report}
\setlength\parindent{0pt}

\usepackage[margin=0.8in]{geometry}
\usepackage{longtable} % For displaying tables across pages

\begin{document}

% ###################################################### PAGE 1: SUMMARY #######################################################
\begin{center}
\Huge\noindent\textbf{A Dynamic PDF Report}  

\end{center}
\vspace{0.5em}

\large{\today}\
\vspace{1em}

% Include the Plotly chart

<<plot_example_1_chart, fig = TRUE , echo = FALSE, warning=FALSE, out.width="100%">>=
 plot_function()
@

%\includegraphics{plot_example_1.png}

\vspace{1em}

% ###################################################### PAGE 2: USER RESPONSES #######################################################
\noindent \textbf{User Responses:}

\begin{longtable}{|c|c|p{8cm}|}
\hline
\textbf{Question} & \textbf{Numeric Response} & \textbf{Text Response} \\ \hline
<<response_table, echo=FALSE, results='asis'>>=
responses <- read.csv("user_responses.csv")
for (i in 1:nrow(responses)) {
  cat(paste0(responses$Question[i], " & ",
             ifelse(is.na(responses$Numeric_Response[i]), "N/A", responses$Numeric_Response[i]), " & ",
             responses$Text_Response[i], " \\\\ \\hline\n"))
}
@
\end{longtable}

\end{document}```

Getting the same (or similar?) here. From RStudio:

api_create(g, filename = β€œtest”)

Returns:
Error in curl::curl_fetch_memory(url, handle = handle): SSL connect error [api.plot.ly]: schannel: next InitializeSecurityContext failed: SEC_E_CERT_EXPIRED (0x80090328) - The received certificate has expired.

Not sure where else to report this. Concerning that it’s gone on for a week without being fixed.

According to https://www.digicert.com/help/:

## TLS Certificate is expired.
The certificate was valid from 02/Apr/2024 through 03/May/2025.

I have emailed @adamschroeder. Hope he can forward to the site maintainer.

Chiming in to report that i have the identical problem. Thank you for diagnosing the specific license expiring further, hopefully will be taken care of soon.