Building Apps with AILesson 32 of 87

Contents

Building Apps with AI

Lesson 32 of 87. Sign in to keep your place.

Module 4 · When it breaks, and getting back

Dependency trouble, and the lock file

8 min read

Your app is mostly other people’s code

A plain Next.js project installs several hundred packages. You chose four of them; the rest arrived as dependencies of dependencies. This is normal, it is how modern software is built, and it is also where a category of failure lives that has nothing to do with your code.

The three files

package.json lists what you asked for, with ranges: "next": "^15.1.0" means 15.1.0 or any later 15.x.

package-lock.json (or pnpm-lock.yaml, or yarn.lock) records exactly which versions were actually installed, all several hundred of them. Commit this file. Without it, your machine and your server can install different versions of the same project and behave differently, which produces the most maddening class of bug in this course.

node_modules is the downloaded result. Never committed, never edited, deletable at any time.

npm install respects the lock file. npm update deliberately ignores it and moves versions forward. Knowing which of those you ran is often the answer to why things changed.

Reading a version number

15.1.3 is major.minor.patch, and the convention says a major bump may break your code deliberately, a minor adds things, a patch fixes things.

The prefix in package.json decides how much movement is allowed. ^15.1.0 accepts any 15.x. ~15.1.0 accepts 15.1.x only. 15.1.0 with no prefix accepts exactly that.

The convention is widely followed and not guaranteed. Plenty of minor releases have broken something for somebody. This is why the lock file exists.

The failures and what they actually mean

Module not found after pulling somebody’s changes. They added a dependency; you have not installed it. npm install.

Two versions of the same library. Two packages each depend on a different version of a third. Symptoms are strange rather than obviously wrong: a React app where hooks throw about invalid calls is the classic. npm ls <package> shows you the tree.

Peer dependency warnings. A package wants a version of something else that you do not have. Sometimes fine, sometimes the actual cause of your problem. Do not reflexively reach for --force or --legacy-peer-deps; they silence the complaint and keep the mismatch.

It broke and I changed nothing. An unpinned range let a new version in on a fresh install. This is exactly what the lock file prevents, which is why deleting it to fix a problem is nearly always the wrong move.

The reinstall ritual

Bash
rm -rf node_modules package-lock.json
npm install

This fixes corrupted installs. It also throws away your record of known-good versions and installs whatever is newest within your ranges, which can introduce a different problem than the one you had.

So try the smaller version first: rm -rf node_modules && npm ci. npm ci installs exactly what the lock file says, nothing newer. If that fixes it, the install was corrupt. If it does not, the lock file was not the problem and deleting it would have taught you nothing while changing several hundred versions.

Every dependency is a decision

An agent asked to add date formatting may install a library rather than write four lines. Each package added is code you did not read, running in your app, with its own dependencies and its own security history.

This is the reason for the standing rule in your rules file: no new dependencies without asking. When one is proposed, three questions are enough. Is it maintained: when was the last release? How many packages does it drag in? Could this be ten lines instead?

Sometimes the answer is clearly yes, install it. Date and time handling, authentication, anything cryptographic: write those yourself and you will get them wrong. The judgement is about whether the problem is hard.

Updating on purpose

Bash
npm outdated       # what has moved on
npm audit          # known vulnerabilities in what you have

Update deliberately, one significant package at a time, with a commit before and a check after. Not the day before a launch, and never all at once: a hundred packages updated together means an unexplained failure has a hundred suspects.

npm audit deserves a note of honesty: it over-reports. Many of its warnings are for build-time tooling that never runs in production, or for attack paths that do not exist in your app. Read what the vulnerability actually is rather than chasing the number to zero.

Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.

Check your understanding

An app that worked last week fails on a colleague’s fresh install, with the same code. What is the most likely cause?

Pick the one you would defend. Your answer stays private.

Next lesson · 8 minIt works here and not there

Stuck on something?Ask Beatriz, your AI tutor

How to cite: Addaly (2026) ‘Dependency trouble, and the lock file’, in Building Apps with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-apps-with-ai/dependency-trouble (Accessed: 13 October 2026).