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 your DESCRIPTION.)
  • 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 runs R CMD INSTALL to make sure that it’s possible to install your package. If this fails, you should run devtools::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 with usethis::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 in inst/CITATION. Rename as needed.

    • The contents of inst/ shouldn’t clash with top-level contents of the package, such as data/ or R/. 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, because devtools::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 use file 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 or Authors and Maintainer. 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 and LinkingTo 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. with check(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 also pak::local_install_deps() and pak::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 or Depends to Suggests.

    • Any packages used in the NAMESPACE must be listed in one of Imports (most commonly) or Depends (only in special cases).

    • Every package listed in Depends must also be imported in the NAMESPACE or accessed with pkg::foo(). If you don’t do this, your package will work when attached to the search path (with library(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 in DESCRIPTION.

    • 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 and Description 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 by parseNamespaceFile() 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) with R_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) with R_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 use require() or library() 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...:

    # BAD
    print.my_class <- function(x) cat("Hi")
    
    # GOOD
    print.my_class <- function(x, ...) cat("Hi")
    
    # Also ok
    print.my_class <- function(x, ..., my_arg = TRUE) cat("Hi")
  • Checking replacement functions. Replacement functions (e.g. functions that are called like foo(x) <- y), must have value 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() (and library.dynam.unload()) should look like library.dynam("name"), not library.dynam("name.dll"). Remove the extension to fix this error.

    • Put library.dynam() in .onLoad(), not .onAttach(); put packageStartupMessage() in .onAttach(), not .onLoad(). Put library.dynam.unload() in .onUnload(). If you use any of these functions, make sure they’re in the right place.

    • Don’t use unlockBinding() or assignInNamespace() 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), like subset() or with(). 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 the Authors@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 update Authors@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 the envir 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 and FALSE in your code (and examples), not T and F.

  • 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 then detach()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 the Encoding() 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 or xz you need to declare at least Depends: R (>= 2.10) in your DESCRIPTION.

    • 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-run devtools::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 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 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 from R CMD check is not usually that helpful, so you may need to look at the log file package.Rcheck/tests/testthat.Rout. Fix any failing tests by iterating with devtools::test().

    Occasionally you may have a problem where the tests pass when run interactively with devtools::test(), but fail when in R 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 .Rbuildignored the build/ directory.
  • Checking installed files from ‘inst/doc’. Don’t put files in inst/doc - keep your vignettes and the files they need in vignettes/.
  • Checking files in ‘vignettes’. Problems here are usually straightforward - you’ve included files that are already included in R (like jss.cls, jss.bst, or Sweave.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 in Suggests. If you really want to use a package and you don’t want to list it in DESCRIPTION, 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) in inst/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.