quarto-dev / quarto-dev/quarto-cli

CI: cold-cache `renv::restore()` fails on 5-package cluster — test setup unusable on forks / fresh caches

Open
#14,711 0 comments 0 reactions 1 assignee View on GitHub

@cderv is already working on this.

Since Jul 20, 2026.

maintenance
Dominant language
JavaScript
Stars
6k
Forks
458
Avg merge
1d 9h
Merged PRs (30d)
41

Description

Symptom

On a runner with no renv package cache, the "Restore R packages" step of
test-smokes.yml fails before any test runs. renv::restore() downloads all
145 lockfile packages, installs 140, and never attempts the remaining
five — reporting only circular "dependency failed" messages with no
underlying install error:

Successfully installed 140 packages in 46 seconds.

The following package(s) were not installed successfully:
- [chromote]: dependency failed (zip)
- [flextable]: dependency failed (flextable, webshot2, officer)
- [officer]: dependency failed (flextable, webshot2, zip)
- [webshot2]: dependency failed (chromote)
- [zip]: dependency failed (flextable, webshot2)

Error: failed to install "chromote", "flextable", "officer", "webshot2", "zip"

Reproduces identically on ubuntu-latest and windows-latest (rules out
compilers/system deps). All five are recorded as normal P3M Repository
entries in tests/renv.lock; their downloads succeed; there is zero
install-attempt output for them between "# Installing packages" and the
failure summary.

  • Environment: renv 1.2.3, R 4.5.2 (lockfile records 4.5.1), P3M binary repo
    (__linux__/noble/latest on Linux), RENV_PATHS_ROOT empty (cache miss).
  • Evidence runs (fork, workflow_dispatch): cderv/quarto-cli runs
    29763939514 / 29763944071 / 29763956751 (all three identical, both OSes).
  • The affected versions entered the lockfile in effe145 ("tests - update
    R env").
Why upstream CI doesn't see it

Every upstream run restores these packages from a warm renv package
cache
(link from cache, no install scheduling), so the failure is latent.
Any cold-cache environment hits it deterministically: new forks, cache
eviction, a runner OS image bump that changes the cache key, or new OS
targets (e.g. future macOS built-version legs). Upstream CI is one
cache-cleanup away from going red in setup.

Reproduction

Dispatch test-smokes.yml on any fork (or clear the
*-renv-* Actions caches upstream) and watch the "Restore R packages"
step. No code changes needed.

Workaround (verified)

Wrapping renv::restore() in try() and downgrading the
renv::status()$synchronized check to a warning lets the run proceed;
the 5 packages are only needed by the docx/screenshot test stack
(flextable/officer/webshot2/chromote/zip consumers), so most of
the suite runs fine without them. Not proposed as the fix — just triage.

Root-cause hypothesis (UNVERIFIED)

The circular "dependency failed" set with no attempted install looks like
renv's install scheduler refusing/deadlocking on a dependency cycle among
this cluster (possibly via Suggests edges, e.g. flextable ⇄ officer,
flextable → webshot2 → chromote). Needs confirmation.

Investigation checklist
  • Minimal reprex: a stripped renv.lock containing only the 5 packages
    (+ hard deps) on a clean machine/container with empty
    RENV_PATHS_ROOT — does it reproduce outside GHA?
  • Does renv > 1.2.3 fix it? (pin newer renv in the bootstrap and re-run
    a fork dispatch)
  • Does RENV_CONFIG_INSTALL_TRANSACTIONAL=FALSE (or staged-install
    settings) change the behavior?
  • Search rstudio/renv issues for the "dependency failed" circular
    pattern; file upstream WITH the minimal reprex if unreported.
  • Check whether a version pin sidesteps it (e.g. previous lockfile
    versions of zip/officer/flextable from before effe145).
  • Consider a CI guard: a scheduled cold-cache canary job (restore with
    RENV_PATHS_ROOT pointed at an empty dir) so cache-masked breakage
    surfaces on purpose instead of by surprise.
  • Lockfile records R 4.5.1, CI installs 4.5.2 — almost certainly
    irrelevant, but confirm while reproducing.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.