Issues with ggiraph plots in a R Shiny app on Connect Cloud

Hello everyone,

I've created a Shiny app using R and Positron. The app includes plots created with the ggiraph package and a table created with the reactable package. Locally, both the plots created with ggiraph and the table created with reactable are generated and displayed correctly. However, after publishing to Posit Connect Cloud, only the table created with reactable appears; the ggiraph plots are not generated. I couldn’t find any errors in the log file, though I might be overlooking something. Can anyone suggest what might be causing this, or is it simply not possible to use ggiraph plots in a Shiny app on Connect Cloud?

Regards,
Patrik

Sample code for a ggiraph plot:

  output$kunden_hist_recency <- renderGirafe({
    req(customer_recency())

    p <- ggplot(customer_recency(), aes(x = recency)) +
      geom_histogram_interactive(
        mapping = aes(
          tooltip = paste0(
            sprintf("Tage: %.0f", x),
            sprintf("\nAnzahl Kunden: %.0f", after_stat(count)),
            sprintf(
              "\nAnteil Kunden: %.1f",
              after_stat(count) /
                sum(after_stat(count)) *
                100
            ),
            "%"
          )
        ),
        colour = "white",
        fill = "#9fc131"
      ) +
      labs(
        x = "Tage seit letzter Bestellung",
        y = "Anzahl Kunden"
      ) +
      theme_minimal(base_size = 10, base_family = "Inter") +
      theme_brand_ggplot2() +
      theme_dp()

    # --- In Girafe konvertieren ---

    girafe(ggobj = p, width_svg = 5.5, height_svg = 2.5) |>
      girafe_options(
        opts_tooltip(
          css = "font-family: Inter; font-size: 0.9rem; color: black; background-color: #f7f7f7; border: 1px solid #e1e5ed; border-radius: 4px; padding: 8px;",
          opacity = 0.9
        ),
        opts_toolbar(hidden = c("selection", "zoom", "misc"))
      )
  })

Local at the top, cloud at the bottom:

Log file:
2026-04-06T15:23:07+02:00 Local Quarto not in use
2026-04-06T15:23:07+02:00 Local R version 4.5.3
2026-04-06T15:23:07+02:00 Local Python not in use
2026-04-06T15:23:07+02:00 No renv.lock found; automatically scanning for dependencies. Default repo: https://cloud.r-project.org
2026-04-06T15:23:07+02:00 Collecting R package descriptions
2026-04-06T15:23:07+02:00 Detect dependencies from project
2026-04-06T15:23:09+02:00 Loading packages from renv.lock
2026-04-06T15:23:09+02:00 Done collecting R package descriptions
2026-04-06T15:23:09+02:00 Preparing files
2026-04-06T15:23:09+02:00 Creating bundle from directory
2026-04-06T15:23:09+02:00 Bundle created
2026-04-06T15:23:09+02:00 Done preparing files
2026-04-06T15:23:09+02:00 Determining content settings
2026-04-06T15:23:09+02:00 Updating content settings
2026-04-06T15:23:12+02:00 Updated content settings
2026-04-06T15:23:12+02:00 Initiating publish of content
2026-04-06T15:23:12+02:00 Publish initiated
2026-04-06T15:23:12+02:00 Uploading files
2026-04-06T15:23:14+02:00 Done uploading files
2026-04-06T15:23:14+02:00 Getting content logs...
2026-04-06T15:23:16+02:00 Waiting for publish to complete
2026-04-06T15:23:16+02:00 Your publish request with ID 808939e4-0ad7-4491-a649-03d6d3ac388c is now being processed.
2026-04-06T15:23:16+02:00 Loading your source code...
2026-04-06T15:23:16+02:00 Installing your code's dependencies into the environment.
2026-04-06T15:23:16+02:00 Collecting your code's R dependencies...
2026-04-06T15:23:17+02:00 Connect Cloud is providing all 148 required R packages:
2026-04-06T15:23:17+02:00 askpass@1.2.1, backports@1.5.0, base64enc@0.1-6, bit@4.6.0, bit64@4.6.0-1
2026-04-06T15:23:17+02:00 blob@1.3.0, boot@1.3-32, brand.yml@0.1.0, broom@1.0.12, bsicons@0.1.2
2026-04-06T15:23:17+02:00 bslib@0.10.0, cachem@1.1.0, callr@3.7.6, cellranger@1.1.0, class@7.3-23
2026-04-06T15:23:17+02:00 cli@3.6.5, clipr@0.8.0, cluster@2.1.8.2, codetools@0.2-20, commonmark@2.0.0
2026-04-06T15:23:17+02:00 conflicted@1.2.0, cpp11@0.5.3, crayon@1.5.3, crosstalk@1.2.2, curl@7.0.0
2026-04-06T15:23:17+02:00 data.table@1.18.2.1, DBI@1.3.0, dbplyr@2.5.2, digest@0.6.39, dplyr@1.2.0
2026-04-06T15:23:17+02:00 dtplyr@1.3.3, evaluate@1.0.5, farver@2.1.2, fastmap@1.2.0, fontawesome@0.5.3
2026-04-06T15:23:17+02:00 fontBitstreamVera@0.1.1, fontLiberation@0.1.0, fontquiver@0.2.1, forcats@1.0.1, foreign@0.8-91
2026-04-06T15:23:17+02:00 fs@2.0.1, gargle@1.6.1, gdtools@0.5.0, generics@0.1.4, ggiraph@0.9.6
2026-04-06T15:23:17+02:00 ggplot2@4.0.2, glue@1.8.0, googledrive@2.1.2, googlesheets4@1.1.2, gtable@0.3.6
2026-04-06T15:23:17+02:00 haven@2.5.5, highr@0.12, hms@1.1.4, htmltools@0.5.9, htmlwidgets@1.6.4
2026-04-06T15:23:17+02:00 httpuv@1.6.17, httr@1.4.8, ids@1.0.1, inventorize@1.1.2, isoband@0.3.0
2026-04-06T15:23:17+02:00 jquerylib@0.1.4, jsonlite@2.0.0, KernSmooth@2.23-26, knitr@1.51, labeling@0.4.3
2026-04-06T15:23:17+02:00 later@1.4.8, lattice@0.22-9, lazyeval@0.2.2, lifecycle@1.0.5, lubridate@1.9.5
2026-04-06T15:23:17+02:00 magrittr@2.0.4, MASS@7.3-65, Matrix@1.7-5, memoise@2.0.1, mgcv@1.9-4
2026-04-06T15:23:17+02:00 mime@0.13, modelr@0.1.11, nlme@3.1-169, nnet@7.3-20, openssl@2.3.5
2026-04-06T15:23:17+02:00 otel@0.2.0, pillar@1.11.1, pkgconfig@2.0.3, plotly@4.12.0, plyr@1.8.9
2026-04-06T15:23:17+02:00 pool@1.0.4, prettyunits@1.2.0, processx@3.8.6, progress@1.2.3, promises@1.5.0
2026-04-06T15:23:17+02:00 ps@1.9.1, purrr@1.2.1, R6@2.6.1, ragg@1.5.2, rappdirs@0.3.4
2026-04-06T15:23:17+02:00 RColorBrewer@1.1-3, Rcpp@1.1.1, reactable@0.4.5, reactR@0.6.1, readr@2.2.0
2026-04-06T15:23:17+02:00 readxl@1.4.5, rematch@2.0.0, rematch2@2.1.2, renv@1.2.0, reprex@2.1.1
2026-04-06T15:23:17+02:00 rlang@1.1.7, RMariaDB@1.3.5, rmarkdown@2.31, rpart@4.1.27, rstudioapi@0.18.0
2026-04-06T15:23:17+02:00 rvest@1.0.5, S7@0.2.1, sass@0.4.10, scales@1.4.0, selectr@0.5-1
2026-04-06T15:23:17+02:00 shiny@1.13.0, shinycssloaders@1.1.0, shinyjs@2.1.1, shinyWidgets@0.9.1, showtext@0.9-8
2026-04-06T15:23:17+02:00 showtextdb@3.0, sourcetools@0.1.7-2, spatial@7.3-18, stringi@1.8.7, stringr@1.6.0
2026-04-06T15:23:17+02:00 survival@3.8-6, svglite@2.2.2, sys@3.4.3, sysfonts@0.8.9, systemfonts@1.3.2
2026-04-06T15:23:17+02:00 textshaping@1.0.5, tibble@3.3.1, tidyr@1.3.2, tidyselect@1.2.1, tidyverse@2.0.0
2026-04-06T15:23:17+02:00 timechange@0.4.0, tinytex@0.59, tzdb@0.5.0, utf8@1.2.6, uuid@1.2-2
2026-04-06T15:23:17+02:00 vctrs@0.7.2, viridisLite@0.4.3, vroom@1.7.1, withr@3.0.2, xfun@0.57
2026-04-06T15:23:17+02:00 xml2@1.5.2, xtable@1.8-8, yaml@2.3.12
2026-04-06T15:23:17+02:00 Using Quarto version: 1.9.36
2026-04-06T15:23:18+02:00 Running on host: deployment-019d627e-44cf39ea2440bfcd5266b8423e16207b-deplohqwdq
2026-04-06T15:23:18+02:00 Process ID: 99
2026-04-06T15:23:18+02:00 Running as user: uid=10002(connect) gid=10002(connect) groups=10002(connect)
2026-04-06T15:23:18+02:00 Connect version: 2026.03.0
2026-04-06T15:23:18+02:00 LANG: C.UTF-8
2026-04-06T15:23:18+02:00 Working directory: /cloud/project
2026-04-06T15:23:18+02:00 Using R 4.5.3
2026-04-06T15:23:18+02:00 R.home(): /opt/R/4.5.3/lib/R
2026-04-06T15:23:18+02:00 Content will use current R environment
2026-04-06T15:23:18+02:00 R_LIBS: (unset)
2026-04-06T15:23:18+02:00 .libPaths(): /cloud/lib/x86_64-pc-linux-gnu-library/4.5, /opt/R/4.5.3/lib/R/library
2026-04-06T15:23:18+02:00 shiny version: 1.13.0
2026-04-06T15:23:18+02:00 httpuv version: 1.6.17
2026-04-06T15:23:18+02:00 rmarkdown version: 2.31
2026-04-06T15:23:18+02:00 knitr version: 1.51
2026-04-06T15:23:18+02:00 jsonlite version: 2.0.0
2026-04-06T15:23:18+02:00 RJSONIO version: (none)
2026-04-06T15:23:18+02:00 htmltools version: 0.5.9
2026-04-06T15:23:18+02:00 reticulate version: (none)
2026-04-06T15:23:18+02:00 Using pandoc: /opt/connect/connect-cloud-2026.03.0/ext/pandoc/2.16
2026-04-06T15:23:18+02:00 Shiny application starting ...
2026-04-06T15:23:18+02:00 Loading required package: showtextdb
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 Attaching package: ‘jsonlite’
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 The following object is masked from ‘package:shiny’:
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 validate
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 Loading required package: ggplot2
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 Attaching package: ‘plotly’
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 The following object is masked from ‘package:ggplot2’:
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 last_plot
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 The following object is masked from ‘package:stats’:
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 filter
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 The following object is masked from ‘package:graphics’:
2026-04-06T15:23:18+02:00
2026-04-06T15:23:18+02:00 layout
2026-04-06T15:23:18+02:00
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 Attaching package: ‘bslib’
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:svglite’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 font_face
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:utils’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 page
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
2026-04-06T15:23:19+02:00 :check_mark: dplyr 1.2.0 :check_mark: readr 2.2.0
2026-04-06T15:23:19+02:00 :check_mark: forcats 1.0.1 :check_mark: stringr 1.6.0
2026-04-06T15:23:19+02:00 :check_mark: lubridate 1.9.5 :check_mark: tibble 3.3.1
2026-04-06T15:23:19+02:00 :check_mark: purrr 1.2.1 :check_mark: tidyr 1.3.2
2026-04-06T15:23:19+02:00 ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
2026-04-06T15:23:19+02:00 :multiply: dplyr::filter() masks plotly::filter(), stats::filter()
2026-04-06T15:23:19+02:00 :multiply: purrr::flatten() masks jsonlite::flatten()
2026-04-06T15:23:19+02:00 :multiply: dplyr::lag() masks stats::lag()
2026-04-06T15:23:19+02:00 :multiply: jsonlite::validate() masks shiny::validate()
2026-04-06T15:23:19+02:00 :information_source: Use the conflicted package to force all conflicts to become errors
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 Attaching package: ‘shinyWidgets’
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:bslib’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 show_toast
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 Attaching package: ‘shinyjs’
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:shinyWidgets’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 alert
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:lubridate’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 show
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:RMariaDB’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 show
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:DBI’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 show
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following object is masked from ‘package:shiny’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 runExample
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 The following objects are masked from ‘package:methods’:
2026-04-06T15:23:19+02:00
2026-04-06T15:23:19+02:00 removeClass, show
2026-04-06T15:23:19+02:00
2026-04-06T15:23:27+02:00
2026-04-06T15:23:27+02:00 Listening on http://127.0.0.1:41409
2026-04-06T15:23:27+02:00 Publish completed successfully

Hi phaecki,

I've had similar issues with missing plots and tables when publishing, even though everything worked perfectly when running the app locally.

Very often, this happens because not all required datasets or assets (like images or specific helper scripts) are included in the automatic upload, or too many non-relevant files are causing conflicts.

You could try to troubleshoot by using manual upload with rsconnect::deployApp() so you have absolute control over which files get uploaded and check out if an adjustment of the upload files leads to a fix. Here is a template you can run in your console:

# Specify exactly which files to upload
data_for_upload <- c(
  "app.R",
  # Add your specific UI assets and data files below:
  # "www/logo.png",
  # "data/customer_data.rds"
)

# Robust deployment script
tryCatch({
  rsconnect::deployApp(
    appName = "your_app_name_here",
    server = "connect.posit.cloud",
    appFiles = data_for_upload,
    forceUpdate = TRUE,       
    launch.browser = FALSE,  
    logLevel = "normal"     
  )
  message("[", Sys.time(), "] Upload successful!")

}, error = function(e) {
  message("[", Sys.time(), "] CRITICAL DEPLOYMENT ERROR: ", e$message)
})

If you're unsure which files your app strictly needs, you can paste your app.R code into an AI and ask it to list all required file dependencies.

If nothing helps i have another idea where the issue relies on. In your code you use a custom font
theme_minimal(base_family = "Inter"). ggiraph renders plots as SVGs. If Posit Connect Cloud has trouble resolving or rendering the "Inter" font, ggiraph will often fail to generate the plot silently without throwing a hard error in the logs, while standard HTML widgets like reactable continue to work just fine.

Try removing base_family = "Inter" for a test run and let me know if the plot suddenly appears on Connect Cloud!

Best :slight_smile:

Hello Gogocoder

Thank you very much for your valuable feedback. I tried both of your suggestions. Unfortunately, neither worked. The plots created with ggiraph still aren't displaying.

:confused: sometimes its hard to find the right solution. Have you think about using plotly instead of ggiraph?

Yes, sometimes it takes patience to achieve the goal. Plotly would actually have been my first choice. However, when I looked into it more closely and stumbled upon their website, I read that they are retiring the R documentation, which put me off. So, I decided to use a different graphics library.