TL;DR
npm WARN package.json <name>@<version> No repository field. is a warning, not an error: the install worked. npm 6 and older print it when a package.json has no repository field. For an application you never publish, add "private": true to package.json and the warning disappears. For a package you publish, add a repository object pointing at the source. On npm 7 and later the warning is gone from npm install; repository issues surface at npm publish instead.
The error
The original Stack Overflow question (917 votes, over 670 000 views) shows it after sudo npm install -g express, as ten lines of the form npm WARN package.json <dependency>@<version> No repository field., one per dependency of Express at the time (range-parser, fresh, methods, cookie-signature, send and others), plus one No readme data. line.
With npm 6 (the release bundled with Node 14), the same check fires on your own project, usually next to two siblings:
npm WARN app-x@1.0.0 No description
npm WARN app-x@1.0.0 No repository field.
npm WARN app-x@1.0.0 No license field.
Why it happens
npm validates the metadata of each package.json it reads. The accepted answer on the question dates the repository check to npm 1.2.20 and links the tracking discussion, npm/npm#3568. Nothing is broken: the field is informational. The package.json reference describes it as the place "where your code lives", useful to contributors and to the npm repo command, which opens the repository in a browser.
The accepted answer also explains why the warning lists packages you never wrote: many published packages simply omit the field. Those lines come from the authors of range-parser, fresh and friends, and no change to your own package.json removes them. The only lever you have over third-party warnings is the npm release you run.
The version matters because the check did not survive npm 7. A bare package.json (just name and version) run through both releases shows it:
mkdir repo-warning-demo && cd repo-warning-demo
printf '{"name":"app-x","version":"1.0.0"}' > package.json
npx -y npm@6 install # prints No description / No repository field. / No license field.
npx -y npm@7 install # prints nothing about package.json metadata
npm 7.0.2 shipped with Node 15.0.0, while Node 14 and Node 12 bundle npm 6 (see the npm column of the Node.js release index). Seeing this warning in 2026 therefore tells you something useful beyond the missing field: the machine, container or CI job is still on npm 6, which usually means an old Node base image.
Find which npm printed it
Before changing any file, establish where the warning comes from. On a laptop, npm -v answers it. In a container or a pipeline, the npm that runs is the one inside the image or the runner, not the one on your machine, so ask the image directly:
# The npm bundled with the base image your Dockerfile uses
docker run --rm node:14-alpine npm -v
# The npm your CI job actually runs (add as the first step of the job)
node -v && npm -v
A 6.x answer from either confirms the diagnosis above. On GitHub Actions the version is whatever actions/setup-node installs, so the fix is a node-version line rather than a package.json edit; this GitHub Actions deploy workflow pinned to Node 20 shows the pattern.
Fix
Pick the step that matches what the project is. Steps 1 and 2 are alternatives; step 3 applies to anything you publish.
1. Application or service: mark it private
A Next.js app, an Express API or an internal tool is never meant to reach the npm registry. Say so:
{
"name": "orders-api",
"version": "1.0.0",
"private": true,
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^5.2.1"
}
}
The private documentation states that npm "will refuse to publish" such a package, which protects you from an accidental npm publish. As the accepted answer on the question points out (and a lower-voted answer notes it also silences the README warning), it also stops npm 6 from printing the metadata warnings: with "private": true, the three lines above vanish from npx npm@6 install. This is the right fix for almost every application, and it is cheaper than inventing a description, licence and repository nobody reads.
Answer 3 on the question suggests "repository": { "private": true } instead, then retracts it as undocumented. Use the top-level private key.
2. Published package: declare the repository
For a library on the npm registry, fill the field in properly. The canonical form is an object:
This is the exact shape Express itself publishes today (npm view express repository --json returns it), so it is a safe model to copy with your own owner and repository name:
{
"repository": {
"type": "git",
"url": "git+https://github.com/expressjs/express.git"
}
}
The reference also accepts shorthands such as "github:user/repo", "gitlab:user/repo" and "bitbucket:user/repo". In a monorepo, add directory so tools land on the package folder rather than the repository root. React's published manifest (npm view react repository --json) is a real example:
{
"repository": {
"type": "git",
"url": "git+https://github.com/react/react.git",
"directory": "packages/react"
}
}
Keep description and license in the same pass: npm 6 checks them alongside repository and reports each one on its own line.
The accepted answer's example uses a git://github.com/... URL. GitHub permanently disabled the unencrypted git:// protocol on 15 March 2022, so use git+https:// as in the npm documentation.
3. Let npm normalise the field before publishing
On npm 7 and later (the pkg command does not exist in npm 6), run:
npm pkg fix
git diff package.json
The npm pkg documentation describes fix as auto-correcting common errors that npm already corrects during publish, which otherwise leaves "subtle (mostly harmless) differences" between your file and the published manifest. With npm 11, a shorthand "repository": "github:expressjs/express" is rewritten to an object whose url carries the git+https prefix shown in step 2.
4. Old runtime: upgrade Node rather than chase warnings
If the warning comes from a CI job or a Docker build, the real finding is npm 6. Moving the image and the runner to a supported Node line removes this class of noise at the source instead of patching each package.json. The nvm, engines and Docker-tag techniques in upgrading Node with nvm and pinning engines so CI cannot regress apply, but substitute a current LTS major (20 or later) for the Node 18 used there, since Node 18 reached end-of-life in April 2025. A current base image such as the node:20-alpine used in this Docker Compose development setup ships npm 9 or 10 depending on the patch release, and neither prints the warning.
Verify the fix
Check what npm now reads from the file:
npm pkg get private repository
npm -v
For an application you expect "private": true; for a library you expect the repository object. For a library, then confirm that the publish path is clean with a dry run, which uploads nothing:
npm publish --dry-run 2>&1 | grep -i "warn" || echo "no publish warnings"
Do not rely on that dry run to test private: npm 11 completes npm publish --dry-run on a private package and prints + app-x@1.0.0 as usual, so npm pkg get private is the check that counts there. On a CI runner, print node -v and npm -v at the top of the job: if npm still reports 6.x, step 4 is the one that matters.
Edge cases the answers skip
The warning moved, it did not disappear. npm 11 prints nothing at install time, but at publish time it reports every correction it made:
npm warn publish npm auto-corrected some errors in your package.json when publishing. Please run "npm pkg fix" to address these errors.
npm warn publish errors corrected:
npm warn publish "repository" was changed from a string to an object
npm warn publish "repository.url" was normalized to "git+https://github.com/expressjs/express.git"
That output comes from a package declaring "repository": "github:expressjs/express". Even the object form triggers the last line when the URL is a plain https:// GitHub address without the git+ prefix. Step 3 silences both for good.
Provenance needs an exact match. When publishing with provenance from GitHub Actions, the provenance documentation requires a public repository in package.json that "matches (case-sensitive) where you are publishing with provenance from". A repository field that was fine for years becomes a publish failure the day provenance is switched on, so check the owner and repository name casing against the workflow's repository.
private is all or nothing. It blocks publishing everywhere. To publish only to a private registry, the private documentation points to publishConfig instead, and then you do want a real repository field.
Yarn Classic behaves differently. Yarn 1.22.22, the current Classic release, on a bare package.json warns No license field but not about the repository, so a project migrated between package managers can gain or lose warnings without any change to the file. Adding "private": true or a license handles that one. If the project is a TypeScript codebase just upgraded to a newer runtime, the TypeScript install and configuration notes for Node 20+ cover the @types/node alignment that usually comes next.
The short version for most readers: an application gets "private": true, a library gets an accurate repository object checked with npm pkg fix, and a machine that still prints this warning on install is running npm 6 and deserves an upgrade more than a quieter package.json.
Originally published at https://www.iloveblogs.blog
Top comments (0)