Why I’ll Never Trust Carets Again



This content originally appeared on DEV Community and was authored by Manuel Artero Anguita 🟨

There once was a good ol’ boy.
Grew up fixing things with instinct and duct tape,
built his apps the same way:
solid, fast, and no time to waste.

(this poem was created by ChatGPT im not hiding it)

good ol boy

One day, though, he had to delete his package-lock.json.

Maybe it got messed up. Maybe Git went weird. Maybe he just wanted a clean install. So he did what any of us would do:

rm package-lock.json && npm i

But that’s when the snake bit the horse.

Because somewhere in his package.json, hiding in plain sight like a viper 🐍 in the grass, were these little traps: ^1.2.3, ^6.0.1

snake-bit

They looked harmless; just caret (^) versions. But those carets were telling npm:

“Yeah, sure, install the latest minor version. What could go wrong?”

And the internet, as always, did moved on.

A dependency of a dependency had released a “compatible” update.

Except it wasn’t.

A function behaved differently. The app crashed. Logs were useless. He didn’t even touch his code, and still… it broke.

All because of a version upgrade he didn’t control.

Cause ^6.0.1 isn’t safe, 6.0.1 is what you do want.

sacrifice

See ya, old buddy.

Other cases i can think of where ^ are going to bite you.

  • CI suddenly start failing: everything works locally. But a new version of a sub-dependency makes your tests fail. You waste hours debugging, thinking you broke something.
  • Two devs. Same codebase. Different node_modules because of ^ pulling different versions. One dev gets a bug. The other can’t reproduce it.
  • Breaking changes hidden in minor updates. If hte npm pacakge don’t follow semver. They might introduce breaking changes in a 1.4.0 that’s technically “safe” for ^1.2.3 (but it isn’t).

How to protect your buddy solve this:

check this script: exact-versions.cjs on GitHub

exact-version.cjs

it will replace all those nasty ^ with the actual version you’ve installed. Read the lock.json and replace the ^ with the correct version.

For instance this could be the output (changes to your package.json):

example diff

walking-by

Ride safe buddy.

— thanks for reading.


This content originally appeared on DEV Community and was authored by Manuel Artero Anguita 🟨