Skip to content

check_*() error on empty input when allow_empty = FALSE (#30) - #33

Merged
shajoezhu merged 3 commits into
mainfrom
30_allow_empty@main
Aug 10, 2026
Merged

check_*() error on empty input when allow_empty = FALSE (#30)#33
shajoezhu merged 3 commits into
mainfrom
30_allow_empty@main

Conversation

@Melkiades

Copy link
Copy Markdown
Contributor

What changes are proposed in this pull request?

  • check_*() functions now error on empty input when allow_empty = FALSE (previously empty but correctly-typed input silently passed class/type checks). (allow_empty updates #30, @Melkiades)

Empty but correctly-typed input (e.g. character(0), numeric(0), 0-row/0-column data frames) previously fell through the empty-handling guard and silently passed the downstream class/type checks even under the default allow_empty = FALSE. The guard is now explicit: it returns invisibly only when allow_empty = TRUE, otherwise it errors. This was applied uniformly across all affected guard sites (check_class(), check_length(), check_range(), check_binary(), check_formula_list_selector(), check_integerish(), check_scalar_integerish(), check_numeric(), and the delegating check_data_frame() / check_logical()).

Downstream consumers (cards, cardx, crane, pager) were scanned: no call site passes a legitimately-empty argument without allow_empty = TRUE, and no consumer test relies on the old silent-pass behavior, so this change is safe.

Reference GitHub issue associated with pull request. closes #30


Pre-review Checklist (if item does not apply, mark is as complete)

  • All GitHub Action workflows pass with a ✅
  • PR branch has pulled the most recent updates from master branch: usethis::pr_merge_main()
  • If a bug was fixed, a unit test was added.
  • If a standalone script was updated, a comment is added to the script header (changelog) AND the last-updated field has been updated.
  • Code coverage is suitable for any new functions/features (generally, 100% coverage for new code): devtools::test_coverage()
  • Request a reviewer

Reviewer Checklist (if item does not apply, mark is as complete)

  • If a bug was fixed, a unit test was added.
  • If a standalone script was updated, a comment is added to the script header (changelog) AND the last-updated field has been updated.
  • Run pkgdown::build_site(). Check the R console for errors, and review the rendered website.
  • Code coverage is suitable for any new functions/features: devtools::test_coverage()

When the branch is ready to be merged:

  • All GitHub Action workflows pass with a ✅
  • Approve Pull Request
  • Merge the PR. Please use "Squash and merge" or "Rebase and merge".
  • Create an issue in any repositories using {standalone} to update the standalone scripts.

Previously, empty but correctly-typed input (e.g. character(0),
numeric(0), 0-row/0-col data frames) silently passed check_*()
class and type checks even under the default allow_empty = FALSE.
The empty-handling guard now errors in that case and only returns
invisibly when allow_empty = TRUE.

Updated the affected guard sites uniformly, added tests covering
empty input for all affected functions, fixed a stale test that
asserted the old behavior, and updated the script changelog and
last-updated field.
@insightsengineering insightsengineering deleted a comment from github-actions Bot Jul 1, 2026
@Melkiades
Melkiades force-pushed the 30_allow_empty@main branch from 0b26b5a to 69bd6cd Compare July 1, 2026 12:07
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

✅ All contributors have signed the CLA
Posted by the CLA Assistant Lite bot.

@Melkiades

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@Melkiades

Copy link
Copy Markdown
Contributor Author

recheck

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates {standalone} input validation so check_*() helpers consistently error on empty inputs when allow_empty = FALSE, aligning behavior with the documented/default expectation and Issue #30.

Changes:

  • Make empty-input handling explicit across multiple check_*() functions (error by default; return invisibly when allow_empty = TRUE).
  • Update/add test coverage to assert the new empty-input behavior.
  • Document the behavior change in the standalone script changelog and NEWS.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
R/standalone-checks.R Tightens guard logic so empty inputs no longer silently pass type/class checks when allow_empty = FALSE.
tests/testthat/test-standalone-checks.R Updates existing expectations and adds a regression test block for empty-input behavior.
NEWS.md Notes the user-visible behavior change for check_*() functions.
Suppressed comments (3)

R/standalone-checks.R:626

  • With the new empty-input erroring behavior, the empty-branch abort currently reuses message ("must be numeric."), which is confusing for numeric(0) because it is numeric. Use a dedicated message for the empty-input branch so the error explains the actual failure condition.
    cli::cli_abort(message, class = c(class, "standalone-checks"), call = call, .envir = envir)

R/standalone-checks.R:508

  • Similar to check_numeric(): in the empty-input branch this abort reuses the general message, which is confusing for integer(0) because it satisfies the "integer vector" predicate (rlang::is_integerish()) but is rejected due to emptiness. Using an explicit empty-input message here will make the failure reason clear.
    cli::cli_abort(message, class = c(class, "standalone-checks"), call = call, .envir = envir)

R/standalone-checks.R:540

  • The default error message text is ungrammatical ("must an scalar integer"). This will surface in snapshots/consumer logs and is easy to correct while touching this function.
  # if empty: return invisibly when allowed, otherwise error
  if (rlang::is_empty(x)) {
    if (isTRUE(allow_empty)) {
      return(invisible(x))
    }
    cli::cli_abort(message, class = c(class, "standalone-checks"), call = call, .envir = envir)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread R/standalone-checks.R
Comment thread R/standalone-checks.R
Comment thread R/standalone-checks.R
Comment thread tests/testthat/test-standalone-checks.R
- fix 'must an' typo in check_integerish/check_scalar_integerish messages
- check_scalar_integerish() now uses its own condition class instead of
  check_integerish, so callers can catch scalar failures specifically
- add empty-input regression tests for check_scalar_integerish and check_length
- update snapshot for the corrected message text
@Melkiades
Melkiades requested a review from mhallal1 August 10, 2026 10:38
@shajoezhu
shajoezhu enabled auto-merge (squash) August 10, 2026 16:08

@shajoezhu shajoezhu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@shajoezhu
shajoezhu merged commit f4891d1 into main Aug 10, 2026
10 checks passed
@shajoezhu
shajoezhu deleted the 30_allow_empty@main branch August 10, 2026 16:08
@github-actions github-actions Bot locked and limited conversation to collaborators Aug 10, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

allow_empty updates

3 participants