System details
R version 4.6.1 (2026-06-24 ucrt)
Platform: x86_64-w64-mingw32/x64
Running under: Windows 11 x64 (build 26200)
Matrix products: default
LAPACK version 3.12.1
locale:
[1] LC_COLLATE=English_United States.utf8 LC_CTYPE=English_United States.utf8 LC_MONETARY=English_United States.utf8
[4] LC_NUMERIC=C LC_TIME=English_United States.utf8
time zone: America/Chicago
tzcode source: internal
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] ggplotplus_0.5.7 shinyvalidate_0.1.3 patchwork_1.3.2 tibble_3.3.1 DT_0.34.0 ggraph_2.2.2
[7] ggplot2_4.0.3 igraph_2.3.3 data.table_1.18.4 scales_1.4.0 Matrix_1.7-5 shinyWidgets_0.9.1
[13] shinydisconnect_0.1.1 waiter_0.2.5.1 shinyjs_2.1.1 stringr_1.6.0 tidyr_1.3.2 dplyr_1.2.1
[19] shiny_1.14.0
loaded via a namespace (and not attached):
[1] gtable_0.3.6 httr2_1.3.0 bslib_0.12.0 htmlwidgets_1.6.4 ggrepel_0.9.8 lattice_0.22-9
[7] vctrs_0.7.3 tools_4.6.1 crosstalk_1.2.2 generics_0.1.4 curl_7.1.0 pkgconfig_2.0.3
[13] checkmate_2.3.4 RColorBrewer_1.1-3 S7_0.2.2 lifecycle_1.0.5 compiler_4.6.1 farver_2.1.2
[19] textshaping_1.0.5 ggforce_0.5.0 graphlayouts_1.2.5 httpuv_1.6.17 htmltools_0.5.9 sass_0.4.10
[25] yaml_2.3.12 later_1.4.8 pillar_1.11.1 jquerylib_0.1.4 MASS_7.3-65 openssl_2.4.2
[31] rsconnect_1.10.1 cachem_1.1.0 viridis_0.6.5 mime_0.13 tidyselect_1.2.1 digest_0.6.39
[37] stringi_1.8.9 purrr_1.2.2 labeling_0.4.3 polyclip_1.10-7 fastmap_1.2.0 grid_4.6.1
[43] cli_3.6.6 magrittr_2.0.5 tidygraph_1.3.1 withr_3.0.3 promises_1.5.0 backports_1.5.1
[49] otel_0.2.0 gridExtra_2.3.1 askpass_1.2.1 ragg_1.5.2 memoise_2.0.1 viridisLite_0.4.3
[55] rlang_1.3.0 Rcpp_1.1.2 xtable_1.8-8 glue_1.8.1 tweenr_2.0.3 pkgload_1.5.3
[61] rstudioapi_0.19.0 jsonlite_2.0.0 R6_2.6.1 systemfonts_1.3.2
Example application or steps to reproduce the problem
library(shiny)
ui <- fluidPage(
actionButton("reset", "Recreate x")
)
server <- function(input, output, session) {
x <- reactiveVal(0)
observe({
cat("Observer saw:", x(), "\n")
})
observeEvent(input$reset, {
x <<- reactiveVal(0) # Rebind x to a new reactiveVal
x(1) # Update the new reactiveVal
})
}
shinyApp(ui, server)
Describe the problem in detail
I don't think this is actually a bug; I think it's the code working as intended. However, I found it unintuitive enough to warrant a mention in the help docs for reactiveVal().
Basically, in "plain R," if you ran x = 15 and then later ran x = 12, you'd overwrite the original object with the new one. However, if you try this with reactiveVal()s, the same doesn't hold true. It seems like instead of overwriting the original, it creates a new one with the same name, creating a second version that observers and other entities could seemingly point at. Perhaps this has something to do with how assignment works in JS versus in R? I dunno.
However, it means that if I am trying to code, say, a reset button, and I try to reset a reactiveVal by essentially just re-running the same command I used to create it, that won't "reset it," but it also won't error, and observers may still find the un-updated reactiveVal and access it instead, so it creates "silent failure states."
It's obvious, in retrospect, that I need to use the reactiveVal as a function to reset it once it's made, but it wasn't obvious before. Just a note in the Details that says something to the effect of "Assigning a reactiveVal to the name of an existing reactiveVal will not overwrite the latter entity; use the reactiveVal as a function to set or reset its value" would have been instructive for me!
System details
Example application or steps to reproduce the problem
Describe the problem in detail
I don't think this is actually a bug; I think it's the code working as intended. However, I found it unintuitive enough to warrant a mention in the help docs for reactiveVal().
Basically, in "plain R," if you ran
x = 15and then later ranx = 12, you'd overwrite the original object with the new one. However, if you try this with reactiveVal()s, the same doesn't hold true. It seems like instead of overwriting the original, it creates a new one with the same name, creating a second version that observers and other entities could seemingly point at. Perhaps this has something to do with how assignment works in JS versus in R? I dunno.However, it means that if I am trying to code, say, a reset button, and I try to reset a reactiveVal by essentially just re-running the same command I used to create it, that won't "reset it," but it also won't error, and observers may still find the un-updated reactiveVal and access it instead, so it creates "silent failure states."
It's obvious, in retrospect, that I need to use the reactiveVal as a function to reset it once it's made, but it wasn't obvious before. Just a note in the Details that says something to the effect of "Assigning a reactiveVal to the name of an existing reactiveVal will not overwrite the latter entity; use the reactiveVal as a function to set or reset its value" would have been instructive for me!