cloudflare / cloudflare/vinext
create-vinext-app leaves pnpm 12 project with an outdated lockfile after ERR_PNPM_IGNORED_BUILDS
- Dominant language
- TypeScript
- Stars
- 8.8k
- Forks
- 406
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 120
Description
## Description
`create-vinext-app` can leave a newly created pnpm 12 project in an inconsistent state when dependency build scripts require approval.
The generated `pnpm-lock.yaml` contains the required Vite and Cloudflare dev dependencies, but those dependencies are missing from `package.json`. As a result, a clean or frozen install fails with `ERR_PNPM_OUTDATED_LOCKFILE`.
The initializer still prints `vinext init complete!` and `Success! Created ...`, even though the generated project cannot be installed in a clean environment.
## Versions
- `create-vinext-app`: `1.0.0-beta.2`
- `vinext`: `1.0.0-beta.9`
- `pnpm`: `12.0.0`
- Node.js: `24.21.0`
- Platform: macOS arm64
- Deployment target: Cloudflare Workers
## Reproduction
```bash
pnpm dlx create-vinext-app@1.0.0-beta.2 \
/tmp/vinext-repro \
--use-pnpm \
--yes \
--disable-git \
--platform=cloudflare
cd /tmp/vinext-repro
pnpm install --frozen-lockfile
```
## Actual behavior
While adding the Cloudflare/Vite dev dependencies, pnpm reports:
```text
Error: ERR_PNPM_IGNORED_BUILDS
Ignored build scripts: esbuild@0.28.1, workerd@1.20260907.1
Run "pnpm approve-builds" to pick which dependencies should be allowed
to run scripts.
```
`create-vinext-app` catches this error and continues:
```text
vinext init complete!
! Dependency installation is waiting for build-script approval
Success! Created vinext-repro at /tmp/vinext-repro
```
However, the resulting `package.json` does not contain:
```json
{
"devDependencies": {
"@cloudflare/vite-plugin": "^1.54.5",
"@vitejs/plugin-react": "^6.1.1",
"@vitejs/plugin-rsc": "^0.5.34",
"vite": "^8.2.2",
"wrangler": "^4.129.1"
}
}
```
The generated `pnpm-lock.yaml` does contain those dependencies.
Therefore, the suggested recovery command is also blocked:
```bash
pnpm approve-builds esbuild workerd
```
```text
Error: ERR_PNPM_OUTDATED_LOCKFILE
Cannot install with "frozen-lockfile" because pnpm-lock.yaml is not
up to date with package.json.
5 dependencies were removed:
@cloudflare/vite-plugin
@vitejs/plugin-react
@vitejs/plugin-rsc
vite
wrangler
```
pnpm also generates unresolved entries in `pnpm-workspace.yaml`:
```yaml
allowBuilds:
esbuild: set this to true or false
workerd: set this to true or false
```
## Expected behavior
When build-script approval is required, `create-vinext-app` should leave the project in a recoverable and internally consistent state:
- `package.json` and `pnpm-lock.yaml` should contain matching dependency declarations.
- `pnpm approve-builds` should be runnable immediately.
- The initializer should not print an unconditional success message if the generated project requires manual recovery.
- Build scripts should not be automatically trusted; the user should still explicitly approve or deny them.
## Why local builds can appear to work
The failed `pnpm add` has already materialized the packages in `node_modules`, so `vinext build` may work in the original directory.
A clean environment, such as a Cloudflare build using `pnpm install --frozen-lockfile`, does not have that existing `node_modules` state and fails before the build starts.
## Suspected cause
The initializer installs runtime dependencies and dev dependencies in separate commands.
The runtime dependency installation succeeds. The dev dependency installation then reaches `esbuild` and `workerd`, updates the lockfile and local installation state, but exits with `ERR_PNPM_IGNORED_BUILDS` before the five requested dev dependencies are persisted to `package.json`.
The error is treated as recoverable here:
https://github.com/cloudflare/vinext/blob/86afc110511c99eb4f654d5b9e3f90c5ff3b8f14/packages/vinext/src/init.ts#L653-L705
The expected dev dependencies are defined here:
https://github.com/cloudflare/vinext/blob/86afc110511c99eb4f654d5b9e3f90c5ff3b8f14/packages/vinext/src/init.ts#L219-L233
pnpm has a related open issue about automatically generated `allowBuilds` placeholders:
https://github.com/pnpm/pnpm/issues/11574
## Workaround
Restore the missing dev dependencies in `package.json` and explicitly resolve the build permissions:
```yaml
# pnpm-workspace.yaml
allowBuilds:
esbuild: true
workerd: true
```
Then run:
```bash
pnpm install --frozen-lockfile
```
Another way to avoid the broken intermediate state is to scaffold with `--skip-install`, configure `allowBuilds`, and then run `pnpm install` separately.
## Suggested regression test
Create a pnpm project where adding the Cloudflare dev dependencies reports `ERR_PNPM_IGNORED_BUILDS`, then verify that:
1. `package.json` and `pnpm-lock.yaml` remain consistent.
2. `pnpm install --frozen-lockfile --ignore-scripts` does not report `ERR_PNPM_OUTDATED_LOCKFILE`.
3. The user can complete the documented build-script approval flow.
Contributor guide
Research direction
Start in packages/vinext/src/init.ts, especially the dependency installation handling at lines 653-705 and the Cloudflare dev dependency list at lines 219-233. Reproduce the pnpm 12 flow with --platform=cloudflare, then add a regression test covering ERR_PNPM_IGNORED_BUILDS. Done means package.json and pnpm-lock.yaml stay consistent, frozen install succeeds, and the approval flow remains explicit without an unconditional success message.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, vite
- Domain
- build-system, cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100