fix(npm): show helpful error when postinstall script hasn't run (#26259)

## Summary
- Replaces empty placeholder executables with shell scripts that print
helpful error messages
- The scripts exit with code 1 instead of silently succeeding with code
0
- Helps users diagnose issues when installing with `--ignore-scripts` or
using pnpm

## Problem
When installing the `bun` npm package with `--ignore-scripts` or using
pnpm (which skips postinstall by default), the placeholder `bun.exe` and
`bunx.exe` files were empty, causing them to silently exit with code 0
and produce no output. This made it very difficult for users to
understand why bun wasn't working.

## Solution
The placeholder files are now shell scripts that:
1. Print a clear error message explaining the issue
2. Provide instructions on how to fix it (manually running postinstall
or reinstalling without `--ignore-scripts`)
3. Exit with code 1 to indicate failure

Example output when running the placeholder:
```
Error: Bun's postinstall script was not run.

This occurs when using --ignore-scripts during installation, or when using a
package manager like pnpm that does not run postinstall scripts by default.

To fix this, run the postinstall script manually:
  cd node_modules/bun && node install.js

Or reinstall bun without the --ignore-scripts flag.
```

## Test plan
- [x] Added regression test that verifies the placeholder script
behavior
- [x] Test passes with `bun bd test test/regression/issue/24329.test.ts`

Fixes #24329

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
robobun
2026-01-19 17:11:38 -08:00
committed by GitHub
parent 04f441453d
commit 704252e85f
2 changed files with 118 additions and 2 deletions

View File

@@ -71,8 +71,23 @@ async function buildRootModule(dryRun?: boolean) {
js: "// Source code: https://github.com/oven-sh/bun/blob/main/packages/bun-release/scripts/npm-postinstall.ts",
},
});
write(join(cwd, "bin", "bun.exe"), "");
write(join(cwd, "bin", "bunx.exe"), "");
// Create placeholder scripts that print an error message if postinstall hasn't run.
// On Unix, these are executed as shell scripts despite the .exe extension.
// On Windows, npm creates .cmd wrappers that would fail anyway if the binary isn't valid.
const placeholderScript = `#!/bin/sh
echo "Error: Bun's postinstall script was not run." >&2
echo "" >&2
echo "This occurs when using --ignore-scripts during installation, or when using a" >&2
echo "package manager like pnpm that does not run postinstall scripts by default." >&2
echo "" >&2
echo "To fix this, run the postinstall script manually:" >&2
echo " cd node_modules/bun && node install.js" >&2
echo "" >&2
echo "Or reinstall bun without the --ignore-scripts flag." >&2
exit 1
`;
write(join(cwd, "bin", "bun.exe"), placeholderScript);
write(join(cwd, "bin", "bunx.exe"), placeholderScript);
write(
join(cwd, "bin", "README.txt"),
`The 'bun.exe' file is a placeholder for the binary file, which