This article explains why sometimes mini-apps experience dependency version clashes and provides a quick fix for when that occurs.
Understanding the pre-built packages
All Workspace R consoles come with some pre-installed packages. Some of these are needed to run the R Console itself, whilst others are commonly used R packages. Adding these common packages as part of the workspace makes it easier and quicker for users to run their mini-apps.
The full list of pre-installed packages can be found in the KB article "Installed R Packages".
Managing packages in the workspace
If an R package is not already prebaked, it can be installed from an R console (preferred option) or a Shiny mini-app.
In this case, a folder with the name of the package is created under files/R/<-r-version>
, where <r-version></r-version>
is the version of R run by the R console or mini-app the package is installed from. The same is done for all of the package dependencies.
So, for example, if we installed the abc package from a 4.0.2 R console, we would get the following new folders:
From then on, all mini-apps and R consoles that use the same R version in that workspace will be able to use the abc
package and any of its dependencies, regardless of when the installation was done or which user or mini-app did the original install.
Pros and Cons
This setup is very useful as it saves storage space and it avoids having to repeatedly pre-install the packages before running a mini-app.
However, there may be situations when a mini-app returns an error because it requires a different version of a package that had been previously installed. The way to fix this will depend on which package is causing the issue.
Troubleshooting Installations
We recommend to follow these steps if your mini-app is experiencing a dependency conflict:
Before running the app for the first time
-
Check whether the packages it needs, or any of their dependencies, have already been installed in the workspace. You can do this by running
xap.check_installed(c('<package1>', '<package2>',...) ) </package2></package1>
-
If they already exist, and they are the right version, you can run your mini-app with the existing packages.
-
If your mini-app requires a different version for one of those packages, or the package had not been previously installed, start a separate rConsole of the same R version the mini-app runs, and install the required package.
If the conflict is with a pre-baked package
You will need to unload the pre-baked package that is causing the conflict before using the correct one.
-
From the mini-app code, locate the script from where libraries are being loaded ( usually
app.R
,global.R
, orui.R
) -
Just after the
.libPaths()
(if used) and before anylibrary()
calls, add the following lines of code:
if (packageVersion(<package-name>) != <required-version>) {
unloadNamespace(<package-name>)
devtools::install_version(</package-name><package-name>, <required-version>)
library(<package-name>)
}
</package-name></required-version></package-name></required-version></package-name>
Where <package-name></package-name>
is the name of the package that is experiencing the conflict, and <required-version></required-version>
is the version you wish to use.
-
If you get the error message such as
namespace <package-name> is imported by <another-package> so cannot be unloaded </another-package></package-name>
you will need to unload the second package’s namespace before unloading the first’s. So for example for:
You should: unloadNamespace("dbplyr")
unloadNamespace("dplyr")
If the conflict is with a package installed by another mini-app
All packages installed from an R console session or another mini-app in the same workspace are saved into the files/R/<r-version></r-version>
folder, where <r-version></r-version>
is the version of R used by the console or mini-app.
In this scenario, to solve a version conflict, you could consider installing your mini-app dependencies in a separate location, adding that folder to the mini-app’s .libPaths
.
From an R console: devtools::install_version('<package-name>', version = '<version>', lib = '<new-location>')</new-location></version></package-name>
The <new-location></new-location>
could be, for example, a subfolder in your mini-app directory.
Then, in the mini-app code, add .libPaths( c(<new-location>, .libPaths()) )</new-location>
before the packages are loaded with either require or library
In the future this scenario will be best addressed by turning the mini-app into a containerised app. This functionality is under active development.
We are also actively working on improvements to how package management is handled in the Workspace, if you encounter any issues or have any feedback it would be greatly appreciated if you could send it to our service desk.