Repository navigation
Fix R-devel R CMD check on GHA - Now temporarily disabled #143
Description
R-CMD-check on R-Devel on GHA fails. Currently I do not know how to fix that. So I will temorarily disable that paericular job - some working tests are better than no tests. Some context especially for AI assistance is below.
Related:
- Impove GHA workflows #135
- Fix R-CMD-check GHA workflow for R-devel: pin roxygen2 7.2.3 on all platforms + tryCatch fallback #141
- Fix R-devel CI: pin roxygen2 7.2.3 on all platforms, add layered tryCatch fallbacks #142
Details
----GHA R-devel Roxygenize Failure — Debug Log & AI Context
Problem Statement
R CMD check on GHA fails exclusively on ubuntu-latest (R-devel).
The error is always one of:
undefined symbol: SET_GROWABLE_BIT— roxygen2.socannot load under R-develERROR: a 'NAMESPACE' file is required— NAMESPACE was deleted before the crash
Root Cause Analysis
C ABI Break in R 4.6.0 (R-devel)
R 4.6.0 (r89670, March 2026) removed SET_GROWABLE_BIT from libR.so exported symbols — it became a static inline in R.h. Any roxygen2 binary compiled against R ≤ 4.5.x references this as an external symbol and cannot be loaded under R-devel.
roxygen2 7.3.x parser_setMethod Bug
roxygen2 ≥ 7.3.0 introduced a bug in parser_setMethod: it calls methods::getMethod(name, eval(call$signature), where = env) with no error handling. In a clean Rscript session, S4 method tables for primitives ([[, [, $, etc.) are not populated → crash.
hyperSpec has ~60+ setMethod() calls on primitives, making it particularly vulnerable.
Timeline of Fix Attempts
✅ Session 1 — all.equal S4 → S3 conversion
- Problem: roxygen2 7.3.3 crashed on
setMethod("all.equal", ...)(S3 generic + S4 registration) - Fix: Converted to S3
all.equal.hyperSpec <- .all.equalwith@method all.equal hyperSpec @export - Outcome: ✅ Fixed locally. NAMESPACE updated to
S3method(all.equal,hyperSpec)
✅ Session 2–3 — Pin roxygen2 to 7.2.3 on GHA
- Problem: roxygen2 7.3.x crashes on
setMethod("[[", ...)(S4 method on primitive) — cannot be fixed without rewriting ~60 S4 methods - Fix: GHA workflow pins to
remotes::install_version("roxygen2", "7.2.3") - Outcome: ✅ Works on macOS/Windows/ubuntu release & oldrel
❌ Session 3 mistake — Removed the pin
- Problem: Pin was removed thinking the
all.equalfix was sufficient - Outcome: ❌ GHA failed on ALL platforms with
parser_setMethodcrash
❌ Attempt A — Pin 7.2.3 binary on R-devel
- Assumption: Same pin would work for R-devel
- Outcome: ❌
undefined symbol: SET_GROWABLE_BIT— binary compiled against older R ABI
❌ Attempt B — Compile roxygen2 7.2.3 from source on R-devel
- Code:
remotes::install_version("roxygen2", "7.2.3", type = "source") - Assumption: Source compilation against R-devel headers would avoid the symbol issue
- Outcome: ❌ Same error — source-compiled 7.2.3 also references
SET_GROWABLE_BITas external symbol (Rcpp or R-internal headers in 7.2.3 still emit the reference)
❌ Attempt C — Skip Roxygenize step on R-devel + restore from git
- Code:
if: matrix.config.r != 'devel'on the Roxygenize step; separate "Restore NAMESPACE" step withgit checkout HEAD -- NAMESPACE man/ - Assumption:
if:condition would prevent Roxygenize from running;setup-r-dependencieswithlocal:.would not wipe NAMESPACE - Outcome: ❌ Still fails —
devtools::document()still runs and still hits theSET_GROWABLE_BITerror - Analysis: Either (a) GHA
if:step conditions don't reliably prevent execution in all scenarios, (b) the GHA run shown was from a pre-fix commit, or (c)setup-r-dependenciesitself triggersdevtools::document()internally via pak's local package installation
❌ Attempt D — tryCatch in Roxygenize step body (current)
- Code: Run Roxygenize on ALL platforms; wrap in
tryCatch; on failuresystem2("git", c("checkout", "HEAD", "--", "NAMESPACE", "man/"))and continue - Rationale: Eliminates reliance on
if:conditions; self-healing; handles ALL failure modes:- Mode 1:
dyn.load(roxygen2.so)fails → error caught → git restore → continue (NAMESPACE NOT wiped) - Mode 2: roxygen2 loads, parser_setMethod crashes after deleting NAMESPACE → error caught → git restore → continue
- Mode 1:
- Removed: Separate "Restore NAMESPACE and man/ from git" step,
sed -i '/^RoxygenNote:/d'DESCRIPTION modification - Outcome: 🔄 Testing
Key Facts
| Fact | Verified |
|---|---|
| roxygen2 7.3.3 RSPM binary fails on R-devel (SET_GROWABLE_BIT) | ✅ Yes |
| roxygen2 7.2.3 RSPM binary fails on R-devel (SET_GROWABLE_BIT) | ✅ Yes |
| roxygen2 7.2.3 source-compiled fails on R-devel (SET_GROWABLE_BIT) | ✅ Yes |
roxygen2 7.3.3 loads on R release (4.5.3) but crashes on [[ setMethod |
✅ Yes |
| roxygen2 7.2.3 works correctly on R release | ✅ Yes |
setup-r-dependencies wipes NAMESPACE |
❓ Unclear — pak does R CMD INSTALL, NOT devtools::document() |
Roxygenize step if: matrix.config.r != 'devel' prevents execution |
❓ Unclear — error still shows in log |
How Similar S4 Repos Handle This
- Bioconductor (
BiocGenerics,S4Vectors,IRanges): Pre-commit NAMESPACE and man/, skip roxygenize in CI, or don't use roxygen2 at all - Matrix CRAN package: Hand-written Rd files, no roxygen2 in CI
- Common pattern: The Roxygenize step uses
tryCatch()→ on failure, restore from git and continue with committed docs
Current Strategy (Attempt D — tryCatch)
Use tryCatch in the Roxygenize step instead of relying on if: conditions:
ok <- tryCatch({
devtools::document()
TRUE
}, error = function(e) {
message("devtools::document() failed: ", conditionMessage(e))
message("Restoring NAMESPACE and man/ from committed versions...")
system2("git", c("checkout", "HEAD", "--", "NAMESPACE", "man/"))
FALSE
})
if (!ok) message("Using committed documentation.")Why this is correct:
- On R-devel:
dyn.load(roxygen2.so)fails before touching NAMESPACE → error caught →git checkoutis a no-op (NAMESPACE intact) → continue with committed docs ✅ - On R-devel (if parker_setMethod crashes after NAMESPACE deletion): error caught →
git checkoutrestores → continue ✅ - On R release/oldrel (with pinned 7.2.3):
devtools::document()succeeds → no error → continue with fresh docs ✅ - No
if:conditions to debug or misfire ✅
Companion changes:
- "Restore NAMESPACE and man/ from git (R-devel)" step removed (handled inside Roxygenize)
sed -i '/^RoxygenNote:/d' DESCRIPTIONremoved (was a hack;RoxygenNoteshould stay)- Session info step re-added (was accidentally dropped) using
sessioninfo::session_info()
How Similar S4 Repositories Handle This
- Bioconductor (
BiocGenerics,S4Vectors,IRanges): Pre-commit NAMESPACE and man/, skip roxygenize in CI entirely, or don't use roxygen2 - Matrix (CRAN): Hand-written Rd files, no roxygen2 in CI pipeline
- Common CRAN S4 packages: Pre-commit docs and use
tryCatchor non-roxygenize CI flows - Best practice: When breaking R API changes occur (like 4.6.0 ABI break), use defensive
tryCatchrather than OS/version conditions
Activity
[-]Fix R-devel check on GHT - Temporarily disabled[/-][+]Fix R-devel R CMD check on GHA - Now temporarily disabled[/+]