Das Symptom
Im package.json steht sauber "engines": { "node": ">=20.0.0" }. Trotzdem
meldet ein Kollege, dass das Projekt bei ihm mit Node 18 seltsam kaputtgeht.
Auf Nachfrage: Ja, npm install sei durchgelaufen. Eine gelbe Zeile sei da
gewesen, glaubt er, aber die Installation hat funktioniert und danach war das
Terminal voll mit anderem Text.
Genauso im CI: Das Deployment läuft auf einem Image mit einer viel zu alten
Node-Version, npm install ist grün, und der Fehler taucht erst zur Laufzeit
auf – irgendwo, wo niemand ihn mit der Node-Version in Verbindung bringt.
Die „Layer 8“-Wahrheit
Das Feld tut genau das, was es soll. Es soll nur weniger, als fast alle
annehmen. Die npm-Doku formuliert es ohne Umschweife: „Unless the user has set
the engine-strict config flag, this field is advisory only and will only
produce warnings when your package is installed as a dependency.“ Beratend. Eine
Warnung. Ein Zettel am Kühlschrank, kein Schloss an der Tür.
Dahinter steckt eine bewusste Machtverteilung, die man mögen kann oder nicht:
Der Paketautor darf sagen, worauf er getestet hat, aber er darf niemandem die
Installation verbieten. Ob diese Angabe verbindlich ist, entscheidet der, der
installiert – über engine-strict, und erst dann wird npm laut Doku „stubbornly
refuse to install (or even consider installing) any package that claims to not
be compatible with the current Node.js version“. Das ist konsequent, aber es
bedeutet eben auch: In einem Projekt, in dem niemand engine-strict gesetzt
hat, hat dein sorgfältig gepflegtes engines-Feld noch nie irgendetwas
verhindert.
Der zweite Teil der Wahrheit ist unbequemer. Selbst mit engine-strict ist die
Sperre kein Bollwerk – sie lässt sich mit --force übergehen. Und --force
steht in erschreckend vielen CI-Skripten, weil es irgendwann irgendein anderes
Problem weggeräumt hat. Wer sich auf engines verlässt, sollte deshalb prüfen,
ob im eigenen Build nicht längst ein Schalter steht, der die Prüfung als
Kollateralschaden mit ausgeschaltet hat.