Graphics display issues with R built from source for RStudio Server

Hi All,

I am having some trouble getting plots to display in our RStudio Server interactive app. We are running this app without Singularity, in the same manner as described in this post. The R interpreter we use for this, we built from source, but I suspect I’m missing some libraries, or compiler flags, or both. When we try to run a plot in RStudio Server, we get this error:

Error in RStudioGD() : 
  Shadow graphics device error: r error 4 (R code execution error)
In addition: Warning message:
In grDevices:::png("/tmp/RtmpHm70aN/206c218b33c34010a3a833ac7bc55509.png",  :
  unable to open connection to X11 display ''

This makes sense, because in a browser window, we wouldn’t have an X11 display device. Some searching around on the internet suggests that we may be missing libcairo, libjpeg, and possibly some others. I have tried building these, and other libraries, into our source build, but I am still unable to resolve this issue.

Does anyone have a recipe for building R from source so that it runs correctly within RStudio Server?

Thanks,
Nick

Actually, I think it could be simpler than that. It seems to be taking issue with /tmp/RtmpHm70aN directory, that you don’t have write access to it?

This is a similar Github issue on the RStudio repo.

Actually, I do have write access to that directory, and to the .png image it’s complaining about. The issue – at least in my reading of the error message – seems to be RStudio’s inability to open the X11 connection.

Here they recommend running capabilities() to check if support is available for various libraries. This is what I get:

> capabilities()
       jpeg         png        tiff       tcltk         X11        aqua    http/ftp     sockets 
      FALSE       FALSE       FALSE       FALSE       FALSE       FALSE        TRUE        TRUE 
     libxml        fifo      cledit       iconv         NLS     profmem       cairo         ICU 
       TRUE        TRUE        TRUE        TRUE        TRUE       FALSE       FALSE       FALSE 
long.double     libcurl 
       TRUE        TRUE 

The output indicates I’m missing support for all the major image types and X11 (among other things).

Nick

I see. OK. here are my capabilities. I think what you need is the png capability. Not sure about X11 but some stack overflow topics seem to indicate you need cario (you see I don’t have X11 but I do have cario).

> capabilities()
       jpeg         png        tiff       tcltk         X11        aqua    http/ftp     sockets      libxml        fifo 
       TRUE        TRUE        TRUE        TRUE       FALSE       FALSE        TRUE        TRUE        TRUE        TRUE 
     cledit       iconv         NLS     profmem       cairo         ICU long.double     libcurl 
       TRUE        TRUE        TRUE       FALSE        TRUE        TRUE        TRUE        TRUE 

Can you run the png() function? I keep getting NULL even though I can link to an image, but I never get an error thrown.

> png()
> png('/tmp/foo')
> foo = png('/tmp/foo')
> png('/users/PZS0714/johrstrom/ondemand/dev/codeserver/icon.png')
> icon = png('/users/PZS0714/johrstrom/ondemand/dev/codeserver/icon.png')

Here’s what I get when I run png():

Error in .External2(C_X11, paste0("png::", filename), g$width, g$height,  : 
  unable to start device PNG
In addition: Warning message:
In png() : unable to open connection to X11 display ''

Re: Cairo, that’s the conclusion I came to as well. That’s why I was wondering if anyone had a recipe for an R source build I could try that has a working graphics component with RStudio Server.

How did you build your R installation?

We had the same issue a while back. It has to do with plotting in R on a headless server. If memory serves, the solution was to add options(bitmapType='cairo') to /{RInstallDir}/lib64/R/etc/Rprofile.site. You might need to create that file if you don’t already have it.

You also need the graphics capabilities. For building R at our site, we use:
./configure --prefix=/apps/R/4.0.0 --enable-R-shlib --with-x --with-cairo --with-jpeglib --with-readline --with-tcltk --with-blas --with-lapack --enable-R-profiling --enable-memory-profiling

It’s been a while since we fixed this so your mileage may vary.

1 Like

thank you @maflister, that was exactly what we needed!
Can anyone weigh in here and explain why that worked?

I speak about as much R as I speak Klingon, so it’s a minor miracle I found this unicorn of a forum post… I’ll provide a more complete scenario to help future searchers:

## this is performed within the "app" 
## (before creating 'Rprofile.site' as suggested)
> require(ggplot2)
  Loading required package: ggplot2
> df <- data.frame(x=1:10,y=1:10)
> plot(df)
> ggplot(df,aes(x=x,y=y)) + geom_point()
> ggsave('/home/jtb49/tmp1.png')
  Saving 4.77 x 2.73 in image
  Error in .External2(C_X11, paste0("png::", filename), g$width, g$height, : 
    unable to start device PNG
  In addition: Warning message:
  In grDevices::png(..., res = dpi, units = "in") :
    unable to open connection to X11 display ''

And our environment after the Rprofile.site fix:

$ module load R
$ RInstallDir=$(which R|sed 's/.bin.R$//')
$ cat $RInstallDir/lib64/R/etc/Rprofile.site
options(bitmapType='cairo')

## and just to verify cairo...
$ Rscript <(echo 'capabilities()')
       jpeg         png        tiff       tcltk         X11        aqua
       TRUE        TRUE        TRUE       FALSE        TRUE       FALSE
   http/ftp     sockets      libxml        fifo      cledit       iconv
       TRUE        TRUE        TRUE        TRUE       FALSE        TRUE
        NLS     profmem       cairo         ICU long.double     libcurl
       TRUE       FALSE        TRUE        TRUE        TRUE        TRUE

Thanks again!
Jason Buechler
High-Performance Computing
Northern Arizona University

I believe that the default graphical device to which graphical output is sent is an X display, which rasterizes the imag. Using

options(bitmapType=‘cairo’)

instructs R to use the cairo rasterizer to create the plot instead of the X device. You might find something useful at

https://stat.ethz.ch/R-manual/R-devel/library/grDevices/html/Devices.html

Just in case it comes up, users can change the bitmapType by including the options() command above with the desired type.

In the following snippet, I set the device to an invalid one, and R prints a list of what it knows about. Using any of the devices that work on Linux and don’t require a display should work (quartz is obviously OS X).

require(ggplot2)
Loading required package: ggplot2
df <- data.frame(x=1:10,y=1:10)
plot(df)
ggplot(df,aes(x=x,y=y)) + geom_point()

options(bitmapType=‘x11’)
ggsave(’/tmp/jtb49/foo.png’)
Saving 7 x 7 in image
Error in match.arg(type) :
‘arg’ should be one of “cairo”, “cairo-png”, “Xlib”, “quartz”

options(bitmapType=‘Xlib’)
ggsave(’/tmp/foo.png’)
Saving 7 x 7 in image
Error in .External2(C_X11, paste0(“png::”, filename), g$width, g$height, :
unable to start device PNG
In addition: Warning message:
In grDevices::png(…, res = dpi, units = “in”) :
unable to open connection to X11 display ‘’

options(bitmapType=‘cairo-png’)
ggsave(’/tmp/foo.png’)

Saving 7 x 7 in image

options(bitmapType=‘cairo’)
ggsave(’/tmp/foo.png’)
Saving 7 x 7 in image

1 Like