Published on Tue Oct 21 2025 21:30:00 GMT+0000 (Coordinated Universal Time) by cresencio
The Error That Won’t Quit
Deployed to Vercel. Build failed. Classic.
MissingSharp: Could not find Sharp.
Please install Sharp (`sharp`) manually into your project
Sure, Sharp was in my package.json. Sure, it was installing. But pnpm 10.x has this lovely security feature where it ignores build scripts by default. Every. Single. Time.
╭ Warning ──────────────────────────────────────╮
│ Ignored build scripts: esbuild, sharp. │
│ Run "pnpm approve-builds" to pick which │
│ dependencies should be allowed to run scripts.│
╰───────────────────────────────────────────────╯
Cool. Very helpful. Except pnpm approve-builds doesn’t work in CI environments like Vercel.
Things I Tried (That Didn’t Work)
1. Created .npmrc
enable-pre-post-scripts=true
ignore-scripts=false
Result: Ignored. pnpm still blocked Sharp’s install scripts.
2. Created .pnpm-approvals.json
{
"approved": ["esbuild", "sharp"]
}
Result: Also ignored. Apparently this isn’t a real thing.
3. Modified vercel.json with various hacks
pnpm install --no-frozen-lockfile- Nopecd node_modules/sharp && npm run install- Nope- Switching to npm entirely - Could work but wanted to keep pnpm locally
What Actually Worked
One simple line in vercel.json:
{
"installCommand": "pnpm install --no-frozen-lockfile && npm rebuild sharp"
}
That’s it. Let pnpm do its thing, then use npm to rebuild Sharp’s native bindings. The npm rebuild command doesn’t care about pnpm’s security theater - it just builds the damn package.
Why This Works
pnpm install --no-frozen-lockfile- Installs all dependencies (Sharp gets downloaded but not built)npm rebuild sharp- Explicitly rebuilds Sharp with its native bindings, bypassing pnpm’s build script restrictions
Sharp needs native bindings for image processing. Without running its install scripts, those bindings never get compiled. npm’s rebuild command forces the compilation to happen.
The Alternative (If You Don’t Care About Image Optimization)
If you just want the build to pass and don’t need image optimization, you can use Astro’s noop image service:
// astro.config.ts
export default defineConfig({
image: {
service: {
entrypoint: 'astro/assets/services/noop'
}
},
// ... rest of config
});
But who wants unoptimized images? Not me.
Lessons Learned
- pnpm 10.x’s build script security is aggressive (maybe too aggressive?)
- Vercel doesn’t let you interactively approve builds
npm rebuild <package>is your friend when fighting package manager wars- Sometimes the simple solution is just using both package managers
Now my images are optimized, my builds pass, and I can go back to writing about sports analytics instead of debugging dependency hell.
TL;DR
Add this to vercel.json:
{
"installCommand": "pnpm install --no-frozen-lockfile && npm rebuild sharp"
}
Move Sharp to dependencies (not devDependencies):
{
"dependencies": {
"sharp": "^0.32.6"
}
}
Commit, push, and watch your Vercel build actually work.
Written by cresencio
← Back to blog