Pitfalls of mixing package managers


In April 2024 I started working with a new team. Since starting my career in web development, I’ve generally stuck with npm for managing dependencies. I’ve seen colleagues switch to Yarn, back to npm, to pnpm and to bun.

While there are many merits to these alternative package managers, I’ve not really felt the need to switch and have found the friction of doing so when working with mixed-focus teams to not really worth it.

Nevertheless, I joined this project and found something a little unusual. All of our scripts and documentation used Yarn features, but in our GitHub Actions…Bun was being used for installation, but still Yarn to run the other commands. Odd.

The speed gains were undeniable. Installing with Bun was really, really fast. I had other priorities to focus on, so was quite happy to leave this as is. Until things broke.

On Friday, I’d left work with green pipelines, our Renovate bot would continue to merge patches and updates over the weekend, and this usually existed without errors.

On Monday, all my pipelines were failing. Every single one. I frantically checked what had been merged. Surely, there was a culprit… but there was nothing. Each pipeline step ran perfectly on my machine, but as soon as I ran the same commit through our CI pipeline: failure. I pushed branches which were previously green and now even they were failing. Something very strange was happening and I was on my own.

Eventually I figured that the cause was that different packages were being installed than expected. You see, on my local machine I’d installed all my dependencies using Yarn and committed my yarn.lock file. As it turned out, Bun ignored Yarn’s lock file and ran a fresh install of everything, bringing in the latest dependencies that satisfied the semver ranges.

As it turns out this had been happening for months without issue, but an incompatible in-range update had broken everything and there was no real way to control this behaviour.

In some ways I’d been here before, 3 years prior. I was rebuilding some ancient project on my client’s development partner’s Jenkins server. A small text change was failing for no discernable reason. It was a similar culprit, the development partners were deleting the lock file from the project before installing, so an in-range dependency update was being pulled in which broke the build and I didn’t have the correct permissions to fix it.

Back in 2024, I didn’t have that issue, I had a brand new one. I had two real choices - the first was to go all-in on a relatively new package manager that I have some real reservations about. I didn’t want to do this.

My other option was to reach for old faithful npm in place of Yarn. Bun would respect the npm lock file and changing over the commands was relatively straightforward. A few changes from how Yarn workspaces worked and we were back in business. The pipeline was green, my stress levels returned to normal.