R Error: 'no package called X', Every Possible Cause and Fix
Error in library(x) : there is no package called 'x' means R searched every folder on its library path but found no installed copy of the package you asked for. The package may be uninstalled, half-installed, installed in a folder R no longer looks at, or hosted somewhere install.packages() can't reach.
What does R's "no package called X" error actually mean?
R looks up packages in a fixed list of folders called the library path. When you call library(somepkg), R walks each folder in order, checks for a somepkg/ subdirectory containing a parsed DESCRIPTION file, and stops at the first match. No match anywhere on the path triggers this error. Before guessing the cause, ask R to show you both lists, what is installed, and where it looked.
The error tells you the exact name R looked up, note that R does not try alternative spellings or capitalizations. find.package() with quiet = TRUE returns an empty character vector when nothing is found, and a folder path when the package exists. This pair, .libPaths() plus find.package(), is the diagnostic backbone for every cause below.
.libPaths() and reported the exact name it searched for. Your fix begins by accepting that R looked correctly, the package really isn't where R looks.Try it: Reproduce the error for a package called ex_fakepkg and confirm with find.package() that R has no copy.
Click to reveal solution
Explanation: The empty character(0) vector means R searched every entry in .libPaths() and found no folder named ex_fakepkg/. The error is genuine, not a session quirk.
Cause 1: Did you forget to install the package?
By far the most frequent reason: you typed library(somepkg) without ever running install.packages("somepkg") first. R does not auto-install missing packages, it only loads what is already on disk. If you copied a script from a tutorial, every library() call near the top has an unwritten prerequisite that the package is already installed on your machine.
The install line is commented out because package installation runs in your local R, not in a browser session. After you run it once, every subsequent library(jsonlite) works without reinstalling. The installed.packages() check is a quick yes/no, useful inside scripts that need to gate a library() call.
requireNamespace("pkg", quietly = TRUE) returns TRUE or FALSE instead of erroring, which lets your script print a friendly install instruction before failing. Reach for it whenever you're shipping code other people will run.Try it: Write a one-liner that uses requireNamespace() to check whether dplyr is installed and prints either "ready" or "missing".
Click to reveal solution
Explanation: requireNamespace() is a non-throwing alternative to library(). It returns a logical you can branch on, so your script never crashes mid-run when a package is absent.
Cause 2: Did install.packages() fail silently?
This trips up users who did run install.packages() and assumed it worked. The function returns invisibly even when a package fails to compile, conflicts with a locked DLL on Windows, or hits a missing system dependency on Linux. R prints warnings, not errors, so if you are not watching the console output, the error reappears the next time you call library().
A folder named 00LOCK-<pkg> inside your library path is the smoking gun. R creates it at the start of an install and removes it on success, if you see one, the install was interrupted (Windows DLL lock, crashed R session, lost network) and never finished. Delete the lock folder before retrying. Asking for the binary type (type = "binary") on Windows and macOS skips local compilation, which is the source of most silent failures.
find.package() after a fresh install before assuming it worked.Try it: Write code that lists every 00LOCK-* folder inside your first library path. Don't delete anything, just print the names.
Click to reveal solution
Explanation: An empty result means no crashed installs are pending. If a name appears, that package's install was interrupted, delete the lock folder and reinstall.
Cause 3: Are your .libPaths() pointing to the wrong folder?
R can read packages from several library folders at once, and it is surprisingly easy for them to get out of sync. You might install into a personal folder while a colleague's script expects the system folder. RStudio projects with renv enable a project-local library that hides your global packages. A package can absolutely be installed on your machine and still be invisible to the current R session, because the session is looking in a different folder.
The sapply() line tells you exactly which library folder owns the package, or whether it lives outside R's search path entirely. If a package is sitting in a folder R isn't checking, you can prepend that folder with .libPaths(c(new_path, .libPaths())). The order matters: R reads from the first folder first, so put your project-local folder ahead of the system folder when you want it to win.
renv, your .libPaths() will point at renv/library/... instead of your global library, and your usual packages will appear "missing." Run renv::status() to confirm the project is using its own library.Try it: Write code that searches every entry in .libPaths() for a folder named dplyr and returns the first matching path (or NA if missing).
Click to reveal solution
Explanation: sapply() returns a logical for each library folder; subsetting .libPaths() by it gives you only the matching folders, and [1] picks the first one R would actually use.
Cause 4: Did you upgrade R and lose your old packages?
Major R upgrades, say from 4.3.x to 4.4.x, create a brand-new library folder named after the new version. Your old folder still exists, but R no longer reads from it, so every package you installed last year suddenly looks "missing." The packages are not gone; they live one folder over, attached to a version of R that is no longer active.
The pattern in the path, library/4.3 versus library/4.4, is your warning sign. R creates a new folder per major.minor version, so the version bump moves you to an empty folder. Listing the old folder gives you the full package set to reinstall; piping that into install.packages() rebuilds your library against the new R version. Reinstalling is safer than copying the folder because compiled C/C++ packages must be rebuilt for each major R version.
Try it: Write code that prints the major.minor version number from R.version.string (e.g., "4.4").
Click to reveal solution
Explanation: R.version$minor is something like "4.2", so sub() strips the patch number. Concatenating with the major version gives the same 4.4 you see in the library folder name.
Cause 5: Is it a Bioconductor package that needs BiocManager?
Bioconductor is a separate R package repository for bioinformatics tools, limma, DESeq2, Biostrings, edgeR, and several hundred others live there, not on CRAN. install.packages("limma") will fail with package 'limma' is not available because CRAN does not host it. You need the BiocManager package as the bridge.
BiocManager::install() accepts both Bioconductor and CRAN names, so once you have it installed you can use it as a drop-in replacement for install.packages(). The Bioconductor team releases two versions a year (April and October) and pins each release to a specific R version, installing into an unsupported R version is the second-most-common cause of trouble after forgetting BiocManager entirely.
BiocManager::version() shows which Bioconductor release matches your R install. If the message says your R version is "out of date for this Bioconductor release," upgrade R first, then reinstall BiocManager.Try it: Write code that checks whether BiocManager is installed (without loading it) and prints "yes" or "no".
Click to reveal solution
Explanation: requireNamespace() checks for the package without attaching it. If it returns FALSE, you need to run install.packages("BiocManager") once before installing any Bioconductor package.
Cause 6: Is it a GitHub-only package that needs remotes::install_github()?
A surprising number of useful R packages live only on GitHub, development versions of CRAN packages, niche tools, internal company packages, or projects whose authors never bothered to submit to CRAN. install.packages() only knows how to fetch from CRAN-style repositories, so it returns the same "not available" warning even when the package very much exists on someone's GitHub page.
The user/repo syntax is a GitHub coordinate, not a package name, once installed, the package is loaded by its actual name (no user prefix). The @ suffix lets you pin to a commit SHA or release tag, which is the only way to make a GitHub install reproducible. devtools::install_github() works the same way and is just remotes::install_github() with extra dependencies.
remotes::install_github("user/repo") installs whatever is on the default branch right now, which can change overnight. For any script that another person will run, append @<commit> or @<tag> so the install is locked.Try it: Write a comment-only block showing how you would install r-lib/cli pinned to release tag v3.6.0 using remotes.
Click to reveal solution
Explanation: The @v3.6.0 suffix tells install_github to check out that exact release tag instead of the default branch. Without it, the install would track moving targets.
How do you stop this error from happening again?
Every cause above shares a root: R does not know what packages your script needs, only what is currently sitting in its library folders. The fix is to make those needs explicit and version-pinned. The lightweight version is sessionInfo() at the bottom of every script. The full version is renv, which records every package and version into a lockfile your collaborators can restore with one command.
The three-field report is the smallest possible fingerprint, paste it at the end of any bug report or issue ticket and the person helping you can immediately spot mismatches. For team projects, escalate to renv: it stores every package version in a renv.lock file that lives in your project, so anyone who clones the repo can restore exactly the same library with renv::restore().
Try it: Write code that prints the names of the first 5 packages in installed.packages() (sorted alphabetically).
Click to reveal solution
Explanation: rownames(installed.packages()) returns every installed package name; sort() puts them in alphabetical order; head(., 5) keeps the first five.
Practice Exercises
Exercise 1: Diagnose where a package actually lives
Write a function find_pkg_folder(pkg) that takes a package name and returns the first .libPaths() entry that contains a folder with that name, or NA_character_ if no entry contains it. Test it on "stats" (a base package) and "thispkgdoesnotexist".
Click to reveal solution
Explanation: sapply() produces a logical vector of which library folders contain a directory named after the package. Subsetting .libPaths() by that vector gives only the matching folders, and [1] picks the first, which is also the one R would use for library().
Exercise 2: Build a safe loader
Write a function safe_library(pkg) that attempts to load pkg with requireNamespace(). If it succeeds, print "loaded: <pkg>". If it fails, print "missing: <pkg> — install with install.packages('<pkg>')". Return TRUE or FALSE invisibly.
Click to reveal solution
Explanation: requireNamespace() returns a logical instead of throwing an error, which is what makes the wrapper safe. Returning the logical with invisible() lets callers branch on the result without cluttering the console.
Exercise 3: Source-aware installer
Write a function install_from(pkg, source) that prints (does not run) the correct install command based on source: "cran", "bioc", or "github". For "github", the input format is "user/repo". Use match.arg() to validate source.
Click to reveal solution
Explanation: match.arg() validates that source is one of the allowed values and lets you abbreviate. switch() picks the matching command template; sprintf() substitutes the package name. Returning the command invisibly lets callers capture and run it later.
Complete Example
Here is a single diagnostic function you can paste at the top of any script that loads packages. It walks through each cause in order and prints the most likely fix.
The function prints every diagnostic an experienced R user would run by hand: the R version, the library path, whether the package is on installed.packages(), whether a 00LOCK folder is left over from a crashed install, and which library folder actually contains it. Running it on a missing package walks you straight to the cause.
Summary
| Cause | Diagnostic | Fix |
|---|---|---|
| 1. Never installed | pkg %in% rownames(installed.packages()) is FALSE |
install.packages("pkg") |
| 2. Install failed silently | 00LOCK-pkg folder in .libPaths()[1] |
Delete lock folder; reinstall with type = "binary" |
| 3. Wrong libPath | Package present in disk folder but not in .libPaths() |
.libPaths(c(folder, .libPaths())) |
| 4. R version upgrade | library/4.X folder in path differs from current R.version |
Reinstall packages against the new R version |
| 5. Bioconductor package | install.packages() says "not available" |
BiocManager::install("pkg") |
| 6. GitHub-only package | install.packages() says "not available" |
remotes::install_github("user/repo") |
| Prevention | sessionInfo() mismatch across machines |
Adopt renv for project libraries |
References
- R Core Team, R Installation and Administration, Add-on packages chapter. Link
- R Core Team,
?library,?install.packages,?find.packagereference pages. - Bioconductor, Install Bioconductor. Link
remotespackage documentation,install_github()reference. Linkrenvpackage, Introduction to renv. Link- Wickham, H. & Bryan, J., R Packages, 2nd Edition. Link
- R FAQ, Common installation issues. Link
Continue Learning
- 50 R Errors Decoded: Plain-English Explanations and Exact Fixes, the parent reference covering every common R error.
- R Error: 'could not find function', Package Not Loaded or Name Conflict?, what to do when the package loaded but a function name still won't resolve.
- R Error: 'object not found', 7 Different Causes, 7 Different Fixes, the sister error for missing variables and datasets.