Repository navigation
Description
Bun version: 1.3.0+b0a6feca5
MacOS Darwin 25.0.0 arm64 arm
Summary
Bun 1.3.0's new default isolated installs with workspaces has two critical bugs that combine to make the catalog feature unusable for production monorepos:
- Catalog fails to deduplicate compatible semver ranges - installs multiple versions even when one would satisfy all requirements
- Cache doesn't clean up on version changes - old versions persist in
.buncache afterbun install, causing runtime errors even after "fixing" package.json
Expected Behavior
When a package is defined in catalog and satisfies all transitive dependency requirements, Bun should:
- Install only ONE version across the entire monorepo
- Clean up old cache entries when versions change in package.json/catalog
Actual Behavior
Bun installs multiple versions of packages in the .bun cache and doesn't clean up old versions, causing:
- Runtime errors (undefined properties from mismatched API versions)
- Build failures
- Requires manual
rm -rf node_modules bun.lock && bun installafter any version change
Reproduction
1. Setup
Monorepo with workspaces + Bun 1.3.0 (isolated installs default)
2. Root package.json
{
"workspaces": ["apps/*", "packages/*"],
"catalog": {
"@convex-dev/auth": "0.0.83",
"@convex-dev/react-query": "0.0.0-alpha.11"
}
}3. Transitive dependency
@convex-dev/[email protected] declares:
{
"dependencies": {
"@convex-dev/auth": "^0.0.83"
}
}4. Expected Result
Single @convex-dev/[email protected] installation (catalog version satisfies ^0.0.83 range)
5. Actual Result
Two installations in bun.lock:
"@convex-dev/auth": ["@convex-dev/[email protected]", ...]
"@convex-dev/react-query/@convex-dev/auth": ["@convex-dev/[email protected]", ...]
Bug 1: Catalog Not Deduplicating Compatible Semver Ranges
Real-World Impact
Example 1: Runtime Error with @convex-dev/auth
Runtime TypeError
Cannot destructure property 'isLoading' of 'useAuth(...)' as it is undefined.
at ConvexAuthNextjsProvider
Cause: Two different installations of @convex-dev/auth with incompatible APIs being loaded by different packages.
Example 2: OpenTelemetry Duplicates
Multiple versions installed: @opentelemetry/[email protected] and @opentelemetry/[email protected]
Bug 2: Cache Not Cleaned on Version Changes
Real-World Impact
After changing catalog from @convex-dev/auth: "0.0.90" to "0.0.83" and running bun install, the .bun cache still contains BOTH versions:
node_modules/.bun/@[email protected]+8c97d86738a1d2ce/
node_modules/.bun/@[email protected]+9bad3111fb0af2d6/
node_modules/.bun/@[email protected]+1c1b59fff7c0c25e/
node_modules/.bun/@[email protected]+eadeca11df4cacdc/
Issues Observed:
- Old versions not removed despite no longer being in package.json
- Same version has multiple cache entries (0.0.83 appears twice with different hashes)
- Requires manual cleanup (
rm -rf node_modules bun.lock && bun install) to get clean state - Stale cache causes runtime errors even after "fixing" package.json
Why This Is Critical:
Even when using overrides to force single versions (workaround for Bug 1), the stale cache from Bug 2 still causes runtime errors. You must manually delete node_modules, bun.lock, and ideally the .bun cache after EVERY version change.
Attempted Workarounds
Overrides (DOES NOT WORK)
We tried adding overrides to force single versions:
{
"overrides": {
"@convex-dev/auth": "0.0.83",
"@convex-dev/react-query": "0.0.0-alpha.11",
"next": "15.5.5",
"@types/react": "19.1.10",
"@types/react-dom": "19.1.4"
}
}Why it fails:
- Bug 2 (cache cleanup) means stale versions remain in
.buncache - Runtime errors persist even with overrides
- Requires manual
rm -rf node_modules bun.lockafter EVERY install - Defeats the purpose of
catalog - Becomes unmaintainable as monorepo grows
Only Working Workaround: Revert to Hoisted Linker
Create bunfig.toml:
[install]
linker = "hoisted"This reverts to Bun 1.2 behavior:
- ✅ Fixes both bugs completely
- ❌ Loses phantom dependency protection that isolated installs provide
- ❌ Makes Bun 1.3's marquee feature (isolated installs) unusable with catalog
Comparison with pnpm
pnpm's isolated installs + catalog/workspace protocol properly deduplicates compatible semver ranges without requiring extensive overrides.
Environment
- Bun: 1.3.0
- OS: macOS 15.0.0 (Darwin 25.0.0)
- Project: Monorepo with Next.js 15, React 19, Convex
- Workspaces:
["apps/*", "packages/*"]
Additional Context
- The issues appear specifically with Bun 1.3's new default isolated installs
- Bun 1.2.x with hoisted linker didn't have these problems
- These two bugs combined make Bun 1.3's
isolated installs + catalogcompletely unusable for production monorepos - The only viable workaround is reverting to hoisted linker, which defeats the purpose of upgrading to Bun 1.3
Suggested Fixes
For Bug 1 (Catalog Deduplication):
When catalog specifies a version that satisfies a transitive dependency's semver range, use the catalog version instead of creating a separate installation in the dependency's isolated cache.
For Bug 2 (Cache Cleanup):
- Clean up unused cache entries in
.bunwhen runningbun install - Remove old versions no longer referenced in
bun.lock - Deduplicate cache entries for the same version (don't create multiple entries with different hashes unless absolutely necessary for peer dependency resolution)
- Provide a
bun install --clean-cacheflag for manual cleanup if needed
Activity
linear commentedon Oct 13, 2025
ENG-20952
dylan-conway commentedon Oct 13, 2025
Sorry you're hitting this bug, we will fix it soon.
For bug#1 we need to save the resolved catalog version to the lockfile along with the specifier. Right now it's only the specifier.
For bug#2 we'll need to an equivalent to modulesCacheMaxAge from pnpm. Currently bun will keep packages in
node_modules/.buneven if they're unused just like pnpm, but there isn't automatic cleanup.haukurmar commentedon Oct 14, 2025
Regarding bug number 2, bun should do a cleanup based on the lockfile everytime when you run bun install in my opinion, keeping those in there breaks the compilation of my app.
I banged my head, trying different things for 8 hours+ even converted into Pnpm which worked well, but then decided to give bun another chance with 1.3 and eventually gave up and went back to the hoisted way :(
I really hope solving these bugs will actually make it work, right now bun is just not usable with a mono repo.
kyle-villeneuve commentedon Oct 15, 2025
I am also noticing some really weird behavior that is similar to this, especially when typescript is involved, because two modules that are essentially the exact same are pointing at different (same node_module version with different hashed symlinks?) and typescript doesn't recognize that the type definitions are the same.
For example:
Overall the node_modules seems pretty janked at the moment, didn't know if it was something weird that I did but maybe it is bun related if others are seeing this.
hastebrot commentedon Oct 15, 2025
@kyle-villeneuve does this issue go away when you downgrade to bun 1.2.23?
there are several known problems with bun 1.3,
bun installand node modules (seebun installtagged issues from last 5 days). I also experienced several issues and downgraded to latest bun 1.2. it seems the issues will be fixed soon.dylan-conway commentedon Oct 15, 2025
Also just want to mention you can use the original hoisted linker with v1.3 with
bun install --linker hoistedor in bunfig.toml:Some projects heavily rely on a hoisted node_modules structure and it might make more sense to continue using it.
haukurmar commentedon Oct 15, 2025
This is exactly the way I went in the end, but it really defeats the purpose isolated installs :)
kyle-villeneuve commentedon Oct 15, 2025
@hastebrot yeah in my case downgrading to 1.2.23 fixed all of the weird node_module issues.
agcty commentedon Oct 21, 2025
For us turning off auto peer dep installation worked. However this means you need to be very explicit about dependencies which can become very cumbersome in large monorepos but as a workaround it seems to work nicely
ArihantBapna commentedon Oct 22, 2025
Another issue we're seeing in our project is with bun 1.3 install times are a LOT slower in our monorepo compared to bun 1.2. Would this be expected with the new isolation feature?
Jarred-Sumner commentedon Oct 23, 2025
We've generally seen installs get faster. If you could provide some kind of reproduction and more details (is this linux or macOS or Windows? do you use network drives?), would love to take a look
ArihantBapna commentedon Oct 24, 2025
Let me see if I can put up a minimal repro of our stack, but structure is as follows:
where shared/* contains shared packages that are used across the stack, and the rest are isolated pieces.
we have our root package.json defining the workspaces as follows
and a bunch of root level overrides for certain packages defined as well.
We are running on macos and linux (garuda locally and alpine on cloud), both of which have had significant slowdown in installs compared to bun 1.2.
Our experience was not the best, we didn't have the bun version locked on Railway (https://railway.com), so we wake up one morning and our deployments start failing due to the version bump 😅 . And we realized the migration was breaking for our monorepo, due to leaky packages (we were using a package in multiple places, without actually installing it in that specific place - totally on us), but what we saw was that with 1.3 this caused install to hang indefinitely.
We also had to bump resources on all instances, because bun install now spikes memory for us, so previously our PR deploy environments would run on 4 gigs of memory and 2vcpu fine, but after update this would crash on the install step with not enough memory.
Let me know what would be useful to help debug this, or if some of these are expected. We love bun and have been using it across our stack building https://eden.so
14 remaining items
install: hoist catalog: peer dependencies like their resolved npm range
fix(ci): unbreak format check + Windows render verification on main
fix(ci): unbreak format check on main + skip cli build:fonts when pre…
fix(ci): switch Windows install to hoisted linker; narrow FormData iter
docs: swap pnpm for Bun as workspace manager + script runner
feat(P1-001): monorepo bootstrap — Bun workspaces + Turborepo + Biome (…
install: hoist catalog: peer dependencies like their resolved npm range
Add Alex Example fixture corpus; force hoisted install linker
fix(ci): unbreak format check on main + skip cli build:fonts when pre…
fix(ci): switch Windows install to hoisted linker; narrow FormData iter
install: hoist catalog: peer dependencies like their resolved npm range
install: pnpm parity — dedupe, prune, pm licenses, audit fix, add --f…
Jarred-Sumner commentedon Aug 14, 2026
@haukurmar — this shipped in #38333.
A
catalog:peer dependency is now hoisted exactly as if the catalog's range were inline, so your@convex-dev/authrepro ends up with one.bunentry. Entries left behind after a catalog change are removed bybun prune:catalog:and the equivalent inline range now produce byte-identical lockfiles and layouts with both linkers.bun dedupe(--checkfor CI) collapses lockfiles that already carry several versions of a package — @mmikhan's question.bun install, so no morerm -rf node_modules bun.lock.bun installstill doesn't delete orphans by itself; that's tracked in install: remove node_modules entries that left the lockfile #32974. Thanks @kyle-villeneuve for the "same version, two+hashfolders" symptom.It'll be in the next canary (
bun upgrade --canary) and in Bun v1.4 — if it doesn't cover your case, comment here.(This comment was written by Claude, on behalf of the Bun team.)
chore: use Bun global store (#2320)