`shiny::paneViewer()` sends Shiny app to Viewer on Mac but NOT on Windows
System details:
Positron and OS details:
Positron Version: 2024.09.0 (system setup) build 77 Code - OSS Version: 1.93.0 Commit: 9b6f7c066546a4c7f104368fc769fb3768b08bfd Date: 2024-09-23T02:44:07.418Z Electron: 30.4.0 Chromium: 124.0.6367.243 Node.js: 20.15.1 V8: 12.4.254.20-electron.0 OS: Windows_NT x64 10.0.22631
Interpreter details:
R 4.4.1
Describe the issue:
When I test graphical outputs from ggplot, using testthat and vdiffr, and a snapshot has changed, I cannot review the old and new snapshot. The console says that the shiny-app that allows you to toggle between old/new snapshot is launched, but nothing happens.
@strengejacke
Thanks for flagging this! We appreciate your help improving Positron. Do you have a reprex for this? I'm trying to create one and using shinytest can't even launch an app properly to record a test. It times out waiting on the app to load but it does seem to be running, just not launched into the Viewer or a browser.
Yes, that's exactly what happens for me, too. In RStudio or VSCode, it works fine.
It sounds like Positron is missing the event to open the app in the Viewer. I'll mark this for further triage.
I was taking a look at this and don't observe a problem myself:
This may be a too-obvious question, but do you have the Shiny extension installed? We do not currently bundle it, but it is needed to run Shiny apps in Positron.
Hm, doesn't seem to solve the problem.
I installed this extension: https://open-vsx.org/extension/posit/shiny
This is the output from Windows
2024-10-08 08:20:01.292 [debug] User data changed
2024-10-08 08:20:01.713 [debug] User data changed
2024-10-08 08:20:15.399 [debug] suggest.durations.json {"entries":[{"providerName":"snippetCompletions","elapsedProvider":1.0999999940395355,"elapsedOverall":1.2000000178813934},{"providerName":"GitHub.vscode-pull-request-github(@)","elapsedProvider":1.241200000004028,"elapsedOverall":14.899999976158142},{"providerName":"GitHub.vscode-pull-request-github(#)","elapsedProvider":1.050199999997858,"elapsedOverall":14.900000005960464},{"providerName":"EdgardMessias.clipboard-manager()","elapsedProvider":3.511499999993248,"elapsedOverall":15.900000005960464},{"providerName":"vscode.positron-r($@:)","elapsedProvider":132.40350000000035,"elapsedOverall":192.69999998807907}],"elapsed":194.19999998807907}
2024-10-08 08:20:45.266 [debug] Comments: URIs of continue on comments to add to storage .
2024-10-08 08:21:17.730 [error] [uncaught exception in main]: Failed to open: Das System kann die angegebene Datei nicht finden. (0x2): Error: Failed to open: Das System kann die angegebene Datei nicht finden. (0x2)
2024-10-08 08:21:45.294 [debug] Comments: URIs of continue on comments to add to storage .
2024-10-08 08:21:48.223 [debug] User data changed
2024-10-08 08:22:21.147 [debug] User data changed
This is the last output in KErnel
[R] 2024-10-08T06:20:22.476408Z ERROR Can't determine if binding is active: Can't find binding `%>%` in environment
[R] at crates\ark\src\lsp\completions\completion_item.rs:386
[R]
The Console output is a bit longer
2024-10-08 08:21:14.553 [info] RECV comm_msg/positron-ui-r-1-9dde2fd1/undefined from iopub: {"header":{"msg_id":"c763c60a-48f5-48b0-b4ae-b4a21446fb96","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:14.551502200+00:00","msg_type":"comm_msg","version":"5.3"},"parent_header":{},"metadata":{},"content":{"comm_id":"positron-ui-r-1-9dde2fd1","data":{"method":"busy","params":{"busy":false}}},"buffers":[]}
2024-10-08 08:21:14.553 [info] RECV comm_msg/positron-ui-r-1-9dde2fd1/undefined from iopub: {"header":{"msg_id":"41eadde2-b156-429f-9424-b28aab6f9c6a","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:14.551537600+00:00","msg_type":"comm_msg","version":"5.3"},"parent_header":{},"metadata":{},"content":{"comm_id":"positron-ui-r-1-9dde2fd1","data":{"method":"prompt_state","params":{"input_prompt":"> ","continuation_prompt":"+ "}}},"buffers":[]}
2024-10-08 08:21:14.553 [info] RECV stream from iopub: {"header":{"msg_id":"2fed3dcc-838a-4bed-a8f0-52d350417ec6","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:14.551560700+00:00","msg_type":"stream","version":"5.3"},"parent_header":{"msg_id":"fragment-dc588309-66b8-4501-9e79-170ecaec54e3","session":"b9fd9a5c4f3126d4019436840618176e","username":"Daniel","date":"2024-10-08T06:20:37.310Z","msg_type":"execute_request","version":"5.0"},"metadata":{},"content":{"name":"stdout","text":"── \u001b[1m\u001b[38;5;214mFailure\u001b[39m (\u001b]8;line = 17:col = 3;file://C:/Users/Daniel/Documents/GitHub/easystats/see/tests/testthat/test-plot.check_dag.R\u0007\u001b[34mtest-plot.check_dag.R:17:3\u001b[39m\u001b]8;;\u0007): `plot()` for check_dag\u001b[22m ────────────────\nSnapshot of `testcase` to 'plot.check_dag/plot-check-dag-all.svg' has changed\nRun \u001b]8;;x-r-run:testthat::snapshot_review('plot.check_dag/')\u0007testthat::snapshot_review('plot.check_dag/')\u001b]8;;\u0007 to review changes\n\u001b[1mBacktrace:\u001b[22m\n\u001b[90m \u001b[39m▆\n\u001b[90m 1. \u001b[39m└─\u001b[1mvdiffr\u001b[22m::expect_doppelganger(title = \"plot.check_dag all\", fig = plot(dag))\u001b[90m at \u001b]8;line = 17:col = 3;file://C:\\Users\\Daniel\\Documents\\GitHub\\easystats\\see\\tests\\testthat\\test-plot.check_dag.R\u0007test-plot.check_dag.R:17:3\u001b]8;;\u0007\u001b[39m\n\u001b[90m 2. \u001b[39m ├─\u001b[1mbase\u001b[22m::withCallingHandlers(...)\n\u001b[90m 3. \u001b[39m └─\u001b[1mtestthat\u001b[22m::expect_snapshot_file(...)\n\n── \u001b[1m\u001b[38;5;214mFailure\u001b[39m (\u001b]8;line = 21:col = 3;file://C:/Users/Daniel/Documents/GitHub/easystats/see/tests/testthat/test-plot.check_dag.R\u0007\u001b[34mtest-plot.check_dag.R:21:3\u001b[39m\u001b]8;;\u0007): `plot()` for check_dag\u001b[22m ────────────────\nSnapshot of `testcase` to 'plot.check_dag/plot-check-dag-current.svg' has changed\nRun \u001b]8;;x-r-run:testthat::snapshot_review('plot.check_dag/')\u0007testthat::snapshot_review('plot.check_dag/')... (truncated)
2024-10-08 08:21:14.553 [info] R kernel status changed: busy => idle
2024-10-08 08:21:14.553 [info] RECV status/idle from iopub: {"header":{"msg_id":"70f50a4c-f855-4819-9e17-58b6ee5a42e9","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:14.551586400+00:00","msg_type":"status","version":"5.3"},"parent_header":{"msg_id":"fragment-dc588309-66b8-4501-9e79-170ecaec54e3","session":"b9fd9a5c4f3126d4019436840618176e","username":"Daniel","date":"2024-10-08T06:20:37.310Z","msg_type":"execute_request","version":"5.0"},"metadata":{},"content":{"execution_state":"idle"},"buffers":[]}
2024-10-08 08:21:15.578 [info] RECV comm_msg/positron-variables-r-0-262d07f5/undefined from iopub: {"header":{"msg_id":"5dbe8e1a-b9aa-48e2-b77d-f7f6f87ad7c6","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:15.577270900+00:00","msg_type":"comm_msg","version":"5.3"},"parent_header":{},"metadata":{},"content":{"comm_id":"positron-variables-r-0-262d07f5","data":{"method":"update","params":{"assigned":[{"access_key":"m_rstan","display_name":"m_rstan","display_value":"[coefficients = 4.786962273580837 0.8858718933938106 -0.7385875138620337 0.46589213208573765 0.5217750514381767 -0.2400644298242216, ses = 0.16270589623155063 0.6069632045241972 0.4929903350455528 0.5306302260317276 0.6862567274526611 0.6495318485550196, fitted.values = 4.964136652259599 4.964136652259599 4.964136652259599 4.964136652259599 4.964136652259599 5.141311030938361, linear.predictors = 4.964136652259599 4.964136652259599 4.964136652259599 4.964136652259599 4.964136652259599 5.141311030938361, residuals = 0.13586334774040054 -0.06413665225959875 -0.2641366522595989 -0.36413665225959946 0.0358633477404009 0.2586889690616392, df.residual = NA, covmat = [[0.026207146164209653 -0.08825977427670813 -0.02444762788521847 -0.023917999368286272 0.0868282907068564 0.08701003059161738]], y = 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 5.4 4.8 4.8 4.3 5.8 5.7 5.4 5.1 5.7 5.1 5.4 5.1 4.6 5.1 4.8 5 5 5.2, model = [150 rows x 3 columns] <data.frame>, data = [150 rows x 5 columns] <data.frame>, family = [family = \"gaussian\", link = \"identity\", linkfun = function (mu) , linkinv = function (eta) , variance = function (mu) , dev.resids = function (y, mu, wt) , aic = function (y, n, mu, wt, dev) , mu.eta = function (eta) , initialize = ??, validmu = function (mu) , valideta = function (eta) , dispersion = NA], offset = NULL, weights = , prior.weights = , contrasts = [Species = \"contr.treatment\"], na.action = NULL, formula = ??, terms = ??, prior.info = [prior = [dist = \"normal\", location = 0 0 0 0 0, scale = 2.5 2.5 2.5 2.5 2.5, adjusted_scale = 2.71... (truncated)
2024-10-08 08:21:17.564 [info] Sending code to R: testthat::snapshot_review('plot.check_dag/')
2024-10-08 08:21:17.564 [info] SEND execute_request to Shell: {"buffers":[],"content":{"code":"testthat::snapshot_review('plot.check_dag/')","allow_stdin":true,"silent":false,"store_history":true,"user_expressions":{},"stop_on_error":false},"header":{"msg_id":"e5747bc2-3e5a-4ea2-a07e-76c89fa44f00","msg_type":"execute_request","version":"5.0","date":"2024-10-08T06:21:17.563Z","session":"b9fd9a5c4f3126d4019436840618176e","username":"Daniel"},"metadata":{},"parent_header":{}}
2024-10-08 08:21:17.565 [info] SEND execute_request: OK
2024-10-08 08:21:17.565 [info] R kernel status changed: idle => busy
2024-10-08 08:21:17.565 [info] RECV status/busy from iopub: {"header":{"msg_id":"587b52b8-f643-4c95-885a-3e31d33b61d3","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:17.564636500+00:00","msg_type":"status","version":"5.3"},"parent_header":{"msg_id":"e5747bc2-3e5a-4ea2-a07e-76c89fa44f00","session":"b9fd9a5c4f3126d4019436840618176e","username":"Daniel","date":"2024-10-08T06:21:17.563Z","msg_type":"execute_request","version":"5.0"},"metadata":{},"content":{"execution_state":"busy"},"buffers":[]}
2024-10-08 08:21:17.566 [info] RECV execute_input from iopub: {"header":{"msg_id":"8c4138c5-3142-4dc0-ad5f-d3cdbb98cf79","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:17.565389300+00:00","msg_type":"execute_input","version":"5.3"},"parent_header":{"msg_id":"e5747bc2-3e5a-4ea2-a07e-76c89fa44f00","session":"b9fd9a5c4f3126d4019436840618176e","username":"Daniel","date":"2024-10-08T06:21:17.563Z","msg_type":"execute_request","version":"5.0"},"metadata":{},"content":{"code":"testthat::snapshot_review('plot.check_dag/')","execution_count":3},"buffers":[]}
2024-10-08 08:21:17.566 [info] RECV comm_msg/positron-ui-r-1-9dde2fd1/undefined from iopub: {"header":{"msg_id":"0d11b8d3-87e1-4dd0-913b-f32770054056","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:17.565869200+00:00","msg_type":"comm_msg","version":"5.3"},"parent_header":{},"metadata":{},"content":{"comm_id":"positron-ui-r-1-9dde2fd1","data":{"method":"busy","params":{"busy":true}}},"buffers":[]}
2024-10-08 08:21:17.699 [info] RECV comm_msg/positron-ui-r-1-9dde2fd1/undefined from iopub: {"header":{"msg_id":"ce0a737b-8f93-4d8b-8f3c-fcdff2cf879b","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:17.698997800+00:00","msg_type":"comm_msg","version":"5.3"},"parent_header":{},"metadata":{},"content":{"comm_id":"positron-ui-r-1-9dde2fd1","data":{"method":"show_url","params":{"url":"C:\\Users\\Daniel\\Documents\\GitHub\\easystats\\see\\http:\\127.0.0.1:4525"}}},"buffers":[]}
2024-10-08 08:21:17.733 [info] RECV stream from iopub: {"header":{"msg_id":"8aab9c64-56e2-4a03-98f3-07fad3bedf56","session":"907b3d88-f735-475d-83ea-1001a090ccca","username":"kernel","date":"2024-10-08T06:21:17.732985100+00:00","msg_type":"stream","version":"5.3"},"parent_header":{"msg_id":"e5747bc2-3e5a-4ea2-a07e-76c89fa44f00","session":"b9fd9a5c4f3126d4019436840618176e","username":"Daniel","date":"2024-10-08T06:21:17.563Z","msg_type":"execute_request","version":"5.0"},"metadata":{},"content":{"name":"stdout","text":"Starting Shiny app for snapshot review\n\u001b[34mℹ\u001b[39m Use Ctrl + C to quit\nLoading required package: shiny\n"},"buffers":[]}
Meanwhile, I updated to the latest Positron:
Positron Version: 2024.10.0 (system setup) build 13
Code - OSS Version: 1.93.0
Commit: 34b5c57cf211bcaf1bc48f75a8cd8d0b4378e5f5
Date: 2024-10-03T16:22:24.120Z
Electron: 30.4.0
Chromium: 124.0.6367.243
Node.js: 20.15.1
V8: 12.4.254.20-electron.0
OS: Windows_NT x64 10.0.22631
Hmmm, that sounds a bit mysterious.
- Can you run any Shiny apps at all? For example,
shiny::runExample("04_mpg")? - Can you run a basic example from diffviewer, like this?
library(diffviewer)
path1 <- tempfile()
path2 <- tempfile()
writeLines(letters, path1)
writeLines(letters[-13], path2)
visual_diff(path1, path2)
- Is this a public R package that I would be able to clone myself to check out?
Hmmm, that sounds a bit mysterious.
- Can you run any Shiny apps at all? For example,
shiny::runExample("04_mpg")?
That works for me!
- Can you run a basic example from diffviewer, like this?
library(diffviewer) path1 <- tempfile() path2 <- tempfile() writeLines(letters, path1) writeLines(letters[-13], path2) visual_diff(path1, path2)
That doesn't do anything.
- Is this a public R package that I would be able to clone myself to check out?
Sure, it's the see package (https://github.com/easystats/see). I was running this test: https://github.com/easystats/see/blob/main/tests/testthat/test-plot.check_dag.R Simply change one of the values in the coords argument, which should modify the plot and thus fail (to call the shiny-app for debugging).
Just let me know if I can help with specific outputs in Positron.
@strengejacke Can you try one more time with the latest release that fixed the problems with HTML in the Viewer on Windows? The diffviewer package generates HTML widgets and I suspect they may have been broken on Windows for the same reason as https://github.com/posit-dev/positron/issues/4940.
Using this version now:
Positron Version: 2024.10.0 (system setup) build 14
Code - OSS Version: 1.93.0
Commit: 901ab5d11d694212d32e53b97f771c5d601e428e
Date: 2024-10-09T15:24:43.348Z
Electron: 30.4.0
Chromium: 124.0.6367.243
Node.js: 20.15.1
V8: 12.4.254.20-electron.0
OS: Windows_NT x64 10.0.22631
Now, the first two examples mentioned here work, but testthat::snapshot_review('plot.check_dag/') still does nothing. There's the red square in the top right of the console, indicating something is busy, but nothing appears on the Viewer pane nor elsewhere. I can use ctrl+c to stop the shiny-app.
Thank you so much! I found the problem; shiny::paneViewer() works in Positron on Mac but not on Windows.
Reprex is here (works on MacOS, does not on Windows):
library(shiny)
runApp(list(
ui = bootstrapPage(
numericInput('n', 'Number of obs', 100),
plotOutput('plot')
),
server = function(input, output) {
output$plot <- renderPlot({ hist(runif(input$n)) })
}),
launch.browser = shiny::paneViewer()
)
Here is what Shiny is doing in this situation:
paneViewer <- function(minHeight = NULL) {
viewer <- getOption("viewer")
if (is.null(viewer)) {
utils::browseURL
} else {
function(url) {
viewer(url, minHeight)
}
}
}
+1 for the fix request
This is quite annoying for package development on Windows. testthat::snapshot_review() is quite useful, and currently I need to open the project also on RStudio IDE to make it work.
FWIW the getOption('viewer') I see on Windows inside Positron is the following
> getOption("viewer")
function(url, height = NULL, ...) {
# Validate the URL argument.
if (!is.character(url) || (length(url) != 1))
stop("url must be a single element character vector.")
# Normalize paths for comparison. This is necessary because on e.g. macOS,
# the `tempdir()` may contain `//` or other non-standard path separators.
normalizedPath <- normalizePath(url, mustWork = FALSE)
normalizedTempdir <- normalizePath(tempdir(), mustWork = FALSE)
# Validate the height argument.
height <- .ps.validate.viewer.height(height)
# Is the URL a temporary file?
if (startsWith(normalizedPath, normalizedTempdir)) {
# Derive a title for the viewer from the path.
title <- .ps.viewer.title(normalizedPath)
# If so, open it in the HTML viewer.
.ps.Call("ps_html_viewer", normalizedPath, title, height, FALSE)
} else {
# If not, open it in the system browser.
utils::browseURL(normalizedPath, ...)
}
}
<environment: 0x0000026142142248>
The problem is with this line in ark https://github.com/posit-dev/ark/blob/40908a3b2ba4c54bba05940ffd536444abf598a0/crates/ark/src/modules/positron/viewer.R#L15
normalizedPath <- normalizePath(url, mustWork = FALSE)
In case of example at https://github.com/posit-dev/positron/issues/4843#issuecomment-2403487936, we have
> url
[1] "http://127.0.0.1:7305"
But on windows, you can't apply normalizePath on a URL. THis is what we get
> normalizedTempdir <- normalizePath(tempdir(), mustWork = FALSE)
> normalizedPath
[1] "c:\\Users\\chris\\Documents\\DEV_R\\quarto-r\\http:\\127.0.0.1:7305"
And this is the path used with utils::browseURL()
} else {
# If not, open it in the system browser.
utils::browseURL(normalizedPath, ...)
}
from https://github.com/posit-dev/ark/blob/40908a3b2ba4c54bba05940ffd536444abf598a0/crates/ark/src/modules/positron/viewer.R#L28-L31
This is windows only problem with normalizePath
On linux this does not modify it
> normalizePath("http://127.0.0.1:7305", mustWork=FALSE)
[1] "http://127.0.0.1:7305"
So this is an issue with ark. Reprex could be
# Run a server from R for the directory
> servr::httd()
To stop the server, run servr::daemon_stop(1) or restart your R session
Serving the directory C:\Users\chris\Documents\DEV_R\quarto-r at http://127.0.0.1:4321
# Set up some trace to see the input
> trace(utils::browseURL,
tracer = quote({
cat(format(Sys.time()), "| browseURL called with URL:", url, "\n")
}),
print = FALSE)
# Use viewer option from ark https://github.com/posit-dev/ark/blob/main/crates/ark/src/modules/positron/viewer.R
> getOption("viewer")("http://127.0.0.1:4321")
2025-05-05 18:21:57 | browseURL called with URL: c:\Users\chris\Documents\DEV_R\quarto-r\http:\127.0.0.1:4321
The url used with utils::browseURL is not valid.
Hope it helps
EDIT: I took the liberty to open in ark as I believe this is where it should be solved.
Verified Fixed
Positron Version(s) : 2025.07.0-49 OS Version(s) : Windows 11
Test scenario(s)
Apps now launch in viewer as expected.
Example:
library(diffviewer)
path1 <- tempfile()
path2 <- tempfile()
writeLines(letters, path1)
writeLines(letters[-13], path2)
visual_diff(path1, path2)