Repository navigation
Conversation
…update pnpm/npm's postinstall hook for puppeteer and playwright downloads a browser binary, which appears to fail in Renovate's own sandbox and breaks its lockfile regeneration step (renovate/artifacts). Every PR that bumps a package.json dependency then fails CI with ERR_PNPM_OUTDATED_LOCKFILE, even though pnpm install resolves fine locally. These env vars only apply to Renovate's own install command, not real CI, so tests still exercise real browsers. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
l2ysho
added a commit
that referenced
this pull request
Sep 14, 2026
…e update (#906) > [!NOTE] > **TL;DR** — fixes the always-failing `renovate/artifacts — Artifact file update failure` job by deleting one line from `renovate.json`. No change to `package.json`; the pnpm guard stays exactly as strict as it is on master. ## Problem Every open Renovate PR is red on `renovate/artifacts` ("Artifact file update failure"), and CI then fails with `ERR_PNPM_OUTDATED_LOCKFILE` — including on PRs that touch no lockfile at all. #855, #846, #797 and #882 are still stuck behind this. ## Root cause The pnpm version was pinned in **three** places, and one of them floated: | Place | Value | |---|---| | `package.json` → `packageManager` | `pnpm@11.13.0` | | `package.json` → `devEngines.packageManager` | `11.13.0`, `onFail: "error"` | | `renovate.json` → `constraints.pnpm` | `^11.0.0` ← floats | Renovate resolved its pnpm from the floating range. Once pnpm 11.13.1 shipped on 2026-07-16, that range started resolving above the guard, so Renovate's `pnpm install` aborted and it never wrote `pnpm-lock.yaml`. No repo commit caused this — the range drifted on its own, which is why `git log` shows nothing. Last successful bot lockfile write: 2026-07-15 (#785, at pnpm 11.13.0). Reproduced on **unmodified master**: - pnpm 11.13.0 → installs fine - pnpm 11.25.0 (what `^11.0.0` resolves to today) → `[ERROR] This project is configured to use 11.13.0 of pnpm. Your current pnpm is v11.25.0` The uv locks still update correctly on the same PRs, which rules out a network or sandbox problem in Renovate's environment. ## Changes `renovate.json` only. `package.json` is byte-identical to master. - **Drop `constraints.pnpm`.** This is the fix. Renovate now reads the version from the `packageManager` field, resolves exactly `11.13.0`, and matches the guard. - `config:base` → `config:recommended`. Deprecated alias that Renovate already maps to the new name. No behaviour change. - `pinVersions: false` → `rangeStrategy: "replace"`. Renovate's `PinVersionsMigration` already rewrote the old key to exactly this, so behaviour is unchanged — but dropping it without the replacement would have fallen back to the `auto` default and changed how every range update is written. - Add `internalChecksFilter: "strict"` explicitly. Already the default, so no behaviour change; the three sibling repos all state it, and stating it here keeps the intent visible if the default ever moves. The last three align this config with `apify/crawlee`, `apify/apify-client-js` and `apify/apify-sdk-js`, none of which declare `constraints`. ## What this deliberately does not do An earlier revision relaxed `devEngines.packageManager.onFail` to `"warn"`. **That is reverted** — the guard is untouched. Two reasons: - It was not needed. The floating `constraints` range was the whole cause. - `onFail` also governs the package-manager *name* check, so `"warn"` stops blocking `npm install` at the repo root. That bypasses every pnpm-only setting in `pnpm-workspace.yaml`: the 1-day `minimumReleaseAge` supply-chain gate, the `allowBuilds` postinstall allowlist, and the `@puppeteer/browsers` override. A range (`^11.13.0`) with `onFail: "error"` also clears the guard, but pnpm string-compares `packageManager` against `devEngines.packageManager`, so it warns `"packageManager" will be ignored` on every command, and corepack rejects a range outright. ## Verification Against a standalone pnpm 11.25.0 (what Renovate resolves) and npm 11.16.0: | Case | Result | |---|---| | ordinary PR branch, exact pin + `onFail: "error"` | exit 0 — the artifacts step stops failing | | master's shape with `constraints` still present | exit 1 — reproduces the bug | | CI path, pnpm 11.13.0, `pnpm install --frozen-lockfile` | exit 0, unchanged | | `npm install` at the repo root | exit 1, `EBADDEVENGINES` — guard intact | `renovate-config-validator` validates the new config. ## Known remaining case A Renovate PR that bumps `packageManager` alone leaves `devEngines` behind and still aborts — #855 does exactly this. That is now **one** red PR instead of the whole queue, and it is fixed by a commit syncing both pins. `apify/crawlee` handles it the same way (apify/crawlee#4050). ## After merge The queued Renovate PRs need a rebase to pick up a valid lockfile. Expect #855, #846, #797 and #882 to go green on their next run. ## Separate follow-ups (not in this PR) - **`pnpm@11.13.0` is deprecated upstream** as a broken release ("Please install pnpm v11.13.1 or newer"); its `@pnpm/exe` build ships without a working binary. Nothing breaks today because `devEngines` only compares version numbers and never downloads. Bumping the pin is a prerequisite for dropping `devEngines` entirely, which is the right long-term shape — without `devEngines` there is no `onFail`, so pnpm defaults to `download`, tries to install the broken 11.13.0, and hard-errors on every install. - **`apify/apify-cli` carries the same bug**: `constraints.pnpm: "^11.0.0"` plus `packageManager: pnpm@11.11.0` against `devEngines` `11.8.0`. It survives only because its `onFail` is `"warn"`, which hides the desync. - #884 proposes a different fix for the same symptom (browser downloads via a `renovate.json` `env` block). That diagnosis does not hold: Renovate's pnpm step runs `--lockfile-only`, which executes no postinstall scripts, and repo-level `env` requires the self-hosted `allowedEnv` allowlist (default `[]`), which the Mend-hosted app does not grant. - Renovate has `automerge: true` with `automergeType: "branch"`, but the org ruleset requires 1 approving review on master — so branch automerge can never fire and the queue piles up. Worth switching to `automergeType: "pr"` with GitHub native auto-merge. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ERR_PNPM_OUTDATED_LOCKFILE, because therenovate/artifactsstep never manages to write back an updatedpnpm-lock.yaml.pnpm install --no-frozen-lockfileresolves cleanly and produces a valid lockfile — the dependency graph is fine, so the problem is in Renovate's own environment, not the repo.puppeteer/playwrightpostinstall scripts download a full browser binary, which appears to fail (network-restricted sandbox) inside Renovate's own artifact-update run.PUPPETEER_SKIP_DOWNLOAD/PLAYWRIGHT_SKIP_BROWSER_DOWNLOADvia Renovate'senvconfig. This only affects the install command Renovate itself runs to compute the lockfile — real CI workflows are untouched and still download real browsers for tests. Verified the resulting lockfile is identical with or without the download.Test plan
renovate/artifactscheck on its next rebaseLint and test) then passespnpm install --frozen-lockfileon that PR