Layer 8Ehrlicher Tech-Support

npm ci bricht ab: package.json und Lockfile nicht synchron

npm ci scheitert, weil Lockfile und package.json auseinanderlaufen. Warum das Absicht ist und warum npm install im CI die falsche Antwort ist.

Aufwand:
ca. 15 Min.

Das Symptom

Lokal läuft alles. Du pushst, der CI-Lauf startet, und schon der Installationsschritt bricht ab: npm ci beschwert sich, dass package.json und package-lock.json nicht zusammenpassen, und beendet sich mit einem Fehler. Kein Test ist gelaufen, keine Zeile Code wurde ausgeführt.

Der naheliegende Reflex im Team ist dann, im CI-Skript npm ci gegen npm install zu tauschen. Der Lauf wird grün. Das Problem ist damit nicht gelöst, sondern nur unsichtbar gemacht.

Die „Layer 8“-Wahrheit

npm ci ist nicht die schnellere Variante von npm install, sondern die strengere. Die npm-Doku sagt trocken: Stimmen die Abhängigkeiten im Package-Lock nicht mit denen in package.json überein, beendet sich npm ci „with an error, instead of updating the package lock“. Das „instead“ ist der ganze Punkt. npm install würde das Lockfile in diesem Moment stillschweigend umschreiben – in einem Wegwerf-Container, dessen Dateisystem in vier Minuten gelöscht ist.

Damit fällt genau die Zusage weg, für die es das Lockfile gibt. Ein Lockfile existiert, damit die Maschine, die deployt, exakt dieselben Versionsnummern installiert wie die Maschine, auf der getestet wurde. npm ci schreibt laut Doku „never … to package.json or any of the package-locks: installs are essentially frozen“. Wer im CI auf npm install ausweicht, tauscht diese Zusage gegen einen grünen Haken.

Der Abbruch ist also keine Zickerei von npm, sondern ein Wächter, der genau das tut, wofür er eingestellt wurde: Er meldet, dass zwei Dateien, die zusammengehören, im Repository auseinanderlaufen. Die Ursache sitzt fast immer zwei Commits vorher, wo jemand eine Version in package.json von Hand angefasst und danach nicht installiert hat. Das Lockfile ist kein Build-Artefakt, das man ignorieren darf – es ist Quelltext.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Die Meldung als Diagnose lesen, nicht als Hindernis

    npm bricht hier bewusst ab: Stimmen die Abhängigkeiten im Package-Lock nicht mit denen in package.json überein, beendet sich npm ci laut Doku mit einem Fehler, statt das Lockfile zu aktualisieren. Der Abbruch ist die Information.

  2. 2.

    Lokal nachziehen – und zwar mit npm install

    Nur npm install darf das Lockfile fortschreiben. Auf dem Entwicklungsrechner ausführen, damit npm den Baum neu auflöst und package-lock.json auf den Stand von package.json bringt:

    npm install
    
  3. 3.

    Das aktualisierte Lockfile mit einchecken

    Der häufigste Grund, warum der Fehler morgen wiederkommt: Die Lockfile-Änderung bleibt im Arbeitsverzeichnis liegen. Sie gehört in denselben Commit wie die Änderung an package.json:

    git add package.json package-lock.json
    git commit -m "Abhaengigkeiten aktualisiert"
    
  4. 4.

    Im CI bei npm ci bleiben

    npm ci entfernt ein vorhandenes node_modules vor der Installation und installiert immer das komplette Projekt. Das ist der Grund, warum CI-Läufe damit reproduzierbar sind – nicht ein Nachteil, den man wegkonfiguriert:

    npm ci
    
  5. 5.

    Erwarten, dass Einzelinstallationen im CI nicht gehen

    Wer im CI-Skript ein einzelnes Paket nachinstallieren will, stößt an eine Grenze der Doku: npm ci installiert nur ganze Projekte, einzelne Abhängigkeiten lassen sich damit nicht hinzufügen. Solche Nachinstallationen gehören in package.json, nicht ins Skript.

Häufige Fragen (FAQ)

?Kann ich im CI nicht einfach npm install statt npm ci nehmen?

Kannst du – dann installierst du aber nicht mehr das, was getestet wurde. npm install darf das Lockfile fortschreiben, npm ci nicht: Laut npm-Doku schreibt npm ci niemals in package.json oder eines der Package-Locks, Installationen sind eingefroren. Genau diese Eigenschaft willst du im CI.

?Warum ist mein Lockfile überhaupt aus dem Tritt geraten?

Fast immer, weil jemand eine Abhängigkeit von Hand in package.json eingetragen oder eine Versionsangabe editiert hat, ohne danach zu installieren. Das Lockfile kennt diese Änderung dann nicht. Auch ein Merge-Konflikt, der nur in package.json gelöst wurde, erzeugt genau diesen Zustand.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler