Appendix A — R CMD check
R CMD check
is composed of over 50 individual checks, described in the following sections. For each check, we briefly describe what it does, what the most common problems are, and how to fix them. When you have a problem with R CMD check
and can’t understand how to fix it, use this list to help figure out what you need to do. To make it easier to understand how the checks fit together, we’ve organised them into sections roughly corresponding to the chapters in this book. This means they will be in a somewhat different order to what you’ll see when you run devtools::check()
, which is our main way of running R CMD check
.
If this chapter doesn’t match up with what you’re seeing, consider that the checks may have changed since this was written. R continues to evolve, including R CMD check
. You may want to consult the most recent online version of this chapter: https://r-pkgs.org/r-cmd-check.html. Please open an issue if you encounter a problem that this chapter doesn’t help with.
At the very end (Section A.12), we highlight some NOTEs that arise during R CMD check
that don’t require any response from you. In general, we recommend eliminating all NOTEs, especially for packages destined for CRAN, but there are a small handful of NOTEs that truly are informational. They are the exception to the rule.
A.1 Check metadata
R CMD check
always starts by describing your current environment.
- Using log directory ‘/some/tmp/path/googledrive.Rcheck’
- Using R version 4.2.2 (2022-10-31)
- Using platform: x86_64-apple-darwin17.0 (64-bit)
- Using session charset: UTF-8
Next the DESCRIPTION
file is parsed and the package version and encoding is printed.
- Checking for file ‘googledrive/DESCRIPTION’
- This is package ‘googledrive’ version ‘2.1.0.9000’
- Package encoding: UTF-8
A.2 Package structure
-
Checking package directory. The directory you’re checking must exist -
devtools::check()
protects you against this problem.
-
Checking if this is a source package. You must check a source package, not a binary or installed package. This should never fail if you use
devtools::check()
.
-
Checking for executable files. You must not have executable files in your package: they’re not portable, they’re not open source, and they are a security risk. Delete any executable files from your package. (If you’re not submitting to CRAN, you can silence this warning by listing each executable file in the
BinaryFiles
field in yourDESCRIPTION
.)
-
Checking for hidden files and directories. On Linux and macOS, files with a name starting with
.
are hidden by default, and you’ve probably included them in your package by mistake. Either delete them, or if they are important, use.Rbuildignore
to remove them from the package bundle. R automatically removes some common directories like.git
and.svn
.
- Checking for portable file names. R packages must work on Windows, Linux and macOS, so you can only use file names that work on all platforms. The easiest way to do this is to stick to letters, numbers, underscores and dashes. Avoid non-English letters and spaces. Fix this check by renaming the listed files.
- Checking for sufficient/correct file permissions. If you can’t read a file, you can’t check it. This check detects the unlikely occurrence that you have files in the package that you don’t have permission to read. Fix this problem by fixing the file permissions.
-
Checking whether package ‘XYZ’ can be installed.
R CMD check
runsR CMD INSTALL
to make sure that it’s possible to install your package. If this fails, you should rundevtools::install()
or the equivalent from RStudio’s menus and debug any problems before continuing.
-
Checking installed package size. It’s easy to accidentally include large files that blow up the size of your package. This check ensures that the whole package is less than 5 MB and each subdirectory is less than 1 MB. If you see this message, check that you haven’t accidentally included a large file.
If submitting to CRAN, you’ll need to justify the size of your package. First, make sure the package is as small as it possibly can be: try recompressing the data, Section 7.1.1; and minimising vignettes, Chapter 17. If it’s still too large, consider moving data into its own package.
-
Checking top-level files. Only specified files and directories are allowed at the top level of the package (e.g.
DESCRIPTION
,R/
,src/
). To include other files, you have two choices:If they don’t need to be installed (i.e. they’re only used for development tasks), add them to
.Rbuildignore
withusethis::use_build_ignore()
.If they need to be installed: move them into
inst/
. They’ll be moved back to the top-level package directory when installed. Learn more in Section 8.2.
-
Checking package subdirectories.
Don’t include any empty directories. These are usually removed automatically by
R CMD build
so you shouldn’t see this error. If you do, just delete the empty directory.The case of files and directories is important. All sub-directories should be lower-case, except for
R/
. A citation file, if present, should be ininst/CITATION
. Rename as needed.The contents of
inst/
shouldn’t clash with top-level contents of the package, such asdata/
orR/
. If they do, rename your files/directories. Learn more in Section 8.2.
- Checking for left-over files. Remove any files listed here. They’ve been included in your package by accident.
A.3 DESCRIPTION
-
Checking DESCRIPTION meta-information.
The
DESCRIPTION
must be valid. You are unlikely to see this error, becausedevtools::load_all()
runs the same check each time you re-load the package.If you use any non-ASCII characters in the DESCRIPTION, you must also specify an encoding. There are only three encodings that work on all platforms: latin1, latin2 and UTF-8. We strongly recommend UTF-8:
Encoding: UTF-8
. Learn more in Section 7.1.3.The
License
must refer to either a known license (a complete list can be found at https://svn.r-project.org/R/trunk/share/licenses/license.db), or it must usefile LICENSE
and that file must exist. Errors here are most likely to be typos. Learn more in Chapter 12.You should either provide
Authors@R
orAuthors
andMaintainer
. You’ll get an error if you’ve specified both, which you can fix by removing the one you didn’t want. Learn more in Section 9.3.
-
Checking package dependencies.
All packages listed in
Depends
,Imports
andLinkingTo
must be installed, and their version requirements must be met, otherwise your package can’t be checked.Packages listed in
Suggests
must be installed, unless you’ve set the environment variable_R_CHECK_FORCE_SUGGESTS_
to a false value (e.g. withcheck(force_suggests = FALSE)
). This is useful if some of the suggested packages are not available on all platforms.An easy way to install any missing or outdated dependencies is to run
devtools::install_deps(dependencies = TRUE)
. See alsopak::local_install_deps()
andpak::local_install_dev_deps()
.R packages can not have a cycle of dependencies: i.e. if package A requires B, then B can not require A (otherwise which one would you load first?). If you see this error, you’ll need to rethink the design of your package. One easy fix is to move the conflicting package from
Imports
orDepends
toSuggests
.Any packages used in the
NAMESPACE
must be listed in one ofImports
(most commonly) orDepends
(only in special cases).Every package listed in
Depends
must also be imported in theNAMESPACE
or accessed withpkg::foo()
. If you don’t do this, your package will work when attached to the search path (withlibrary(mypackage)
) but will not work when only loaded (e.g.mypackage::foo()
)
-
Checking CRAN incoming feasibility. These checks only apply if you’re submitting to CRAN.
If you’re submitting a new package, you can’t use the same name as an existing package. You’ll need to come up with a new name.
If you’re submitting an update, the version number must be higher than the current CRAN version. Update the
Version
field inDESCRIPTION
.If the maintainer of the package has changed (even if it’s just a change in email address), the new maintainer should submit to CRAN, and the old maintainer will receive an email prompting them to confirm the change.
You must use a standard open source license, as listed in https://svn.r-project.org/R/trunk/share/licenses/license.db. You can not use a custom license as CRAN does not have the legal resources to review custom agreements.
The
Title
andDescription
must be free from spelling mistakes. The title of the package must be in title case. Neither title nor description should include either the name of your package or the word “package”. Reword your title and description as needed.If you’re submitting a new package, you’ll always get a
NOTE
. This reminds the CRAN maintainers to do some extra manual checks.Avoid submitting multiple versions of the same package in a short period of time. CRAN prefers at most one submission per month. If you need to fix a major bug, be apologetic.
A.4 Namespace
-
Checking if there is a namespace. You must have a
NAMESPACE
file. This is handled for your automatically by the devtools workflow.
-
Checking package namespace information. The
NAMESPACE
should be parseable byparseNamespaceFile()
and valid. If this check fails, it’s a bug in roxygen2.
-
Checking whether the package can be loaded with stated dependencies. Runs
library(pkg)
withR_DEFAULT_PACKAGES=NULL
, so the search path is empty (i.e. stats, graphics, grDevices, utils, datasets and methods are not attached like usual). Failure here typically indicates that you’re missing a dependency on one of those packages.
-
Checking whether the namespace can be loaded with stated dependencies. Runs
loadNamespace(pkg)
withR_DEFAULT_PACKAGES=NULL
. Failure usually indicates a problem with the namespace.
A.5 R code
- Checking R files for non-ASCII characters. For maximum portability (i.e. so people can use your package on Windows) you should avoid using non-ASCII characters in R files. It’s ok to use them in comments, but object names shouldn’t use them, and in strings you should use unicode escapes. See the CRAN-specific notes in Chapter 6 for more details.
-
Checking R files for syntax errors. Obviously your R code must be valid. You’re unlikely to see this error if you’ve been regularly using
devtools::load_all()
.
-
Checking dependencies in R code. Errors here often indicate that you’ve forgotten to declare a needed package in the
DESCRIPTION
. Remember that you should never userequire()
orlibrary()
inside a package - see Section 9.6, Chapter 10, and Chapter 11 for more details on best practices.Alternatively, you may have accidentally used
:::
to access an exported function from a package. Switch to::
instead.
-
Checking S3 generic/method consistency. S3 methods must have a compatible function signature with their generic. This means that the method must have the same arguments as its generic, with one exception: if the generic includes
...
the method can have additional arguments.A common cause of this error is defining print methods, because the
print()
generic contains...
:
-
Checking replacement functions. Replacement functions (e.g. functions that are called like
foo(x) <- y
), must havevalue
as the last argument.
-
Checking R code for possible problems. This is a compound check for a wide range of problems:
Calls to
library.dynam()
(andlibrary.dynam.unload()
) should look likelibrary.dynam("name")
, notlibrary.dynam("name.dll")
. Remove the extension to fix this error.Put
library.dynam()
in.onLoad()
, not.onAttach()
; putpackageStartupMessage()
in.onAttach()
, not.onLoad()
. Putlibrary.dynam.unload()
in.onUnload()
. If you use any of these functions, make sure they’re in the right place.Don’t use
unlockBinding()
orassignInNamespace()
to modify objects that don’t belong to you.codetools::checkUsagePackage()
is called to check that your functions don’t use variables that don’t exist. This sometimes raises false positives with functions that use non-standard evaluation (NSE), likesubset()
orwith()
. Generally, we think you should avoid NSE in package functions, and hence avoid this NOTE, but if you can not, see?globalVariables
for how to suppress this NOTE.You are not allowed to use
.Internal()
in a package. Either call the R wrapper function, or write your own C function. (If you copy and paste the C function from base R, make sure to maintain the copyright notice, use a GPL-2 compatible license, and list R-core in theAuthors@R
field.)Similarly you are not allowed to use
:::
to access non-exported functions from other packages. Either ask the package maintainer to export the function you need, or write your own version of it using exported functions. Alternatively, if the licenses are compatible you can copy and paste the exported function into your own package. If you do this, remember to updateAuthors@R
.Don’t use
assign()
to modify objects in the global environment. If you need to maintain state across function calls, create your own environment, as described in Section 7.4.Don’t use
attach()
in your code. Instead refer to variables explicitly.Don’t use
data()
without specifying theenvir
argument. Otherwise the data will be loaded in the global environment.Don’t use deprecated or defunct functions. Update your code to use the latest versions.
You must use
TRUE
andFALSE
in your code (and examples), notT
andF
.
-
Checking whether the package can be loaded. R loads your package with
library()
. Failure here typically indicates a problem with.onLoad()
or.onAttach()
.
-
Checking whether the package can be unloaded cleanly. Loads with
library()
and thendetach()
es. If this fails, check.onUnload()
and.onDetach()
.
-
Checking whether the namespace can be unloaded cleanly. Runs
loadNamespace("pkg"); unloadNamespace("pkg")
. Check.onUnload()
for problems.
-
Checking loading without being on the library search path. Calls
library(x, lib.loc = ...)
. Failure here indicates that you are making a false assumption in.onLoad()
or.onAttach()
.
A.6 Data
-
Checking contents of ‘data’ directory.
The data directory can only contain file types described in Section 7.1.
Data files can contain non-ASCII characters only if the encoding is correctly set. This usually shouldn’t be a problem if you’re saving
.Rdata
files. If you do see this error, look at theEncoding()
of each column in the data frame, and ensure none are “unknown”. (You’ll typically need to fix this somewhere in the import process). Learn more in Section 7.1.3.If you’ve compressed a data file with
bzip2
orxz
you need to declare at leastDepends: R (>= 2.10)
in yourDESCRIPTION
.If you’ve used a sub-optimal compression algorithm for your data, re-compress with the suggested algorithm.
A.7 Documentation
If you’re grappling with documentation problems specifically, you may be able to iterate more quickly by using devtools::check_man()
, which attempts to run only the relevant subset of checks. It also automatically calls devtools::document()
for you.
-
Checking Rd files. This checks that all
man/*.Rd
files use the correct Rd syntax. If this fails, it indicates a bug in roxygen2.
-
Checking Rd metadata. Names and aliases must be unique across all documentation files in a package. If you encounter this problem you’ve accidentally used the same
@name
or@aliases
in multiple places; make sure they’re unique.
- Checking Rd line widths. Lines in Rd files must be less than 90 characters wide. This is unlikely to occur if you wrap your R code, and hence roxygen comments, to 80 characters. For very long URLs, use a link-shortening service like bit.ly.
- Checking Rd cross-references. Errors here usually represent typos.
-
Checking for missing documentation entries. All exported objects must be documented. See
?tools::undoc
for more details.
-
Checking for code/documentation mismatches. This check ensures that the documentation matches the code. This should never fail because you’re using roxygen2 which automatically keeps them in sync and
check()
should usually re-document()
your package. In any case, the solution is often to re-rundevtools::document()
.
-
Checking Rd
\usage
sections. All arguments must be documented, and all@params
must document an existing argument. You may have forgotten to document an argument, forgotten to remove the documentation for an argument that you’ve removed, or misspelled an argument name.S3 and S4 methods need to use special
\S3method{}
and\S4method{}
markup in the Rd file. Roxygen2 will generate this for you automatically.
-
Checking Rd contents. This checks for auto-generated content made by
package.skeleton()
. Since you’re not usingpackage.skeleton()
you should never have a problem here.
-
Checking for unstated dependencies in examples. If you use a package only for an example, make sure it’s listed in the
Suggests
field. Learn more about how to use different types of dependencies in your examples in Chapter 11.
- Checking examples. Every documentation example must run without errors, and must not take too long. See Section 16.5 for details.
-
Checking PDF version of manual. Occasionally you’ll get an error when building the PDF manual. This is usually because the pdf is built by latex and you’ve forgotten to escape something. Debugging this is painful - your best bet is to look up the latex logs and combined tex file and work back from there to
.Rd
files then back to a roxygen comment. Any such failure is potentially a bug in roxygen2, so open an issue.
A.8 Demos
-
Checking index information. If you’ve written demos, each demo must be listed in
demo/00Index
. The file should look like:demo-name-without-extension Demo description another-demo-name Another description
A.9 Compiled code
-
Checking foreign function calls.
.Call()
,.C()
,.Fortran()
,.External()
must always be called either with aNativeSymbolInfo
object (as created with@useDynLib
) or use the.package
argument. See?tools::checkFF
for more details.
- Checking line endings in C/C++/Fortran sources/headers. Always use LF as a line ending.
- Checking line endings in Makefiles. As above.
-
Checking for portable use of
$(BLAS_LIBS)
and$(LAPACK_LIBS)
. Errors here indicate an issue with your use of BLAS and LAPACK.
- Checking compiled code. Checks that you’re not using any C functions that you shouldn’t.
A.10 Tests
- Checking for unstated dependencies in tests. Every package used by tests must be included in the dependencies.
-
Checking tests. Each file in
tests/
is run. If you’ve followed the instructions in Chapter 13 you’ll have at least one file:testthat.R
. The output fromR CMD check
is not usually that helpful, so you may need to look at the log filepackage.Rcheck/tests/testthat.Rout
. Fix any failing tests by iterating withdevtools::test()
.Occasionally you may have a problem where the tests pass when run interactively with
devtools::test()
, but fail when inR CMD check
. This usually indicates that you’ve made a faulty assumption about the testing environment, and it’s often hard to figure it out.
A.11 Vignettes
This is a tricky enough topic that it also receives substantial coverage in the main body of the book; see Section 17.5.
-
Checking ‘build’ directory.
build/
is used to track vignette builds. It’s hard to imagine how this check could fail unless you’ve accidentally.Rbuildignore
d thebuild/
directory.
-
Checking installed files from ‘inst/doc’. Don’t put files in
inst/doc
- keep your vignettes and the files they need invignettes/
.
-
Checking files in ‘vignettes’. Problems here are usually straightforward - you’ve included files that are already included in R (like
jss.cls
,jss.bst
, orSweave.sty
), or you have leftover latex compilation files. Delete these files.
-
Checking for sizes of PDF files under ‘inst/doc’. If you’re making PDF vignettes, you can make them as small as possible by running
tools::compactPDF()
.
-
Checking for unstated dependencies in vignettes. As with tests, every package that you use in a vignette must be listed in the
DESCRIPTION
. If a package is used only for a vignette, and not elsewhere, make sure it’s listed inSuggests
. If you really want to use a package and you don’t want to list it inDESCRIPTION
, write an article instead of a vignette.
-
Checking package vignettes in ‘inst/doc’. This checks that every source vignette (i.e.
.Rmd
) has a built equivalent (i.e..html
) ininst/doc
. This shouldn’t fail if you’ve used the standard process outlined in Chapter 17. If there is a problem, start by checking your.Rbuildignore
.
-
Checking running R code from vignettes. The R code from each vignette is run. If you want to deliberately execute errors (to show the user what failure looks like), make sure the chunk has
error = TRUE, purl = FALSE
.
- Checking re-building of vignette outputs. Each vignette is re-knit to make sure that the output corresponds to the input. Again, this shouldn’t fail in normal circumstances.
A.12 NOTEs that are informational
Our blanket advice is to eliminate all ERRORs, WARNINGs, and even NOTEs that you see in R CMD check
. But there are a few exceptions, i.e. there are a couple of NOTEs that do you not need to fix (and, indeed, probably can not fix).
A.12.1 Initial CRAN submission
When a package first goes to CRAN, there will always be one NOTE that alerts the CRAN maintainers that this is a new submission and that they’ll need to do some extra checks. You can’t eliminate this NOTE.
* checking CRAN incoming feasibility ... NOTE
Maintainer: 'Jane Doe <jane@example.com>'
New submission
A.12.2 Non-ASCII characters in data
If your package’s data contains non-ASCII characters, you will get a NOTE like this, but it does not necessarily mean you need to do anything about it.
Check: data for non-ASCII characters
Result: NOTE
Note: found 25 marked UTF-8 strings
As long as you are aware of the non-ASCII characters and the NOTE mentions your intended and declared encoding (preferably UTF-8), all is well.
A.12.3 Rd cross-references
If your roxygen comments contain a cross-reference to a package that is not a formal, direct dependency, you might see a NOTE like this:
Check: Rd cross-references
Result: NOTE
Undeclared package ‘jsonlite’ in Rd xrefs
This could happen if you want to document something related to a hard indirect dependency: There’s a legitimate reason to link to a topic in the other package and it is basically guaranteed to be installed. Therefore, in practice, often more good than harm comes from the cross-reference.
In our experience, this NOTE is only seen on certain CRAN check flavors and not others. Thus far, we have never been directed to address this NOTE by CRAN maintainers.