The problem
Every package.json dependency is checked for staleness, and no project can say "yes, this one is old, and we know". The staleness warning is the only check such a dependency gets, and it is the only warning in Update-time that a single reference can neither silence nor put on a threshold of its own.
The README's answer does not answer this: "A package.json dependency takes no marker, because npm and pnpm update it rather than Update-time rewriting its lines. Opt one out by declaring an upper bound or an exact version instead." An upper bound opts the dependency out of updates, which is a different question. A dependency deliberately kept at a version whose project has gone quiet keeps warning at every run, and the only ways to stop it are to raise --stale-after for the whole scan or to disable the check entirely.
Every other reference Update-time warns about takes an ignore[stale] or an ignore[stale<DAYS]. This one cannot, for want of somewhere to write it.
What the file will accept
package.json is strict JSON, so the marker cannot be a comment. Probed 2026-08-15 with the installed npm:
Written into package.json |
npm's answer |
// update-time: ignore[stale] on its own line |
npm error code EJSONPARSE … package.json must be actual JSON, not just JavaScript |
"//": "update-time: ignore[stale]" |
accepted; npm pkg get reads the rest of the file back |
"update-time": { "left-pad": "ignore[stale]" } |
accepted; npm pkg get update-time returns it and npm install --package-lock-only succeeds |
A field it is, then, and it has to name the dependency it applies to, since a package.json declares many.
Scope
- Decide where a marker for a
package.json dependency is written, and which dependency each one names.
- Honour the
stale scope in both its forms: ignore[stale] silences the warning, and ignore[stale<90] (or allow[stale>=90]) puts that dependency on a threshold of its own.
- Report every other scope as redundant, with the reason each is:
update, a bound, and cooldown steer an update npm and pnpm make rather than Update-time, and yanked and vulnerable name checks a range-declared dependency does not get. hash-drift is redundant too, since the integrity hashes live in the lock file.
The design constraint
Every marker Update-time reads today is found by position: on the reference's own line, or on the line above it. A field-based marker is found by name, so the reference has to be identified rather than located. Reading and validating the directive text is unaffected — that is the Marker domain's work and takes a string.
Locating the reference itself is already solved: package_json.dependency_locations() returns each declared dependency with the line of every entry declaring it, which is where the staleness warning is already reported. A name declared in more than one section carries a location per entry, so a marker naming that dependency has to say whether it covers all of them.
Out of scope
- The Node engine version in the same file, which is a different reference with a different set of checks, covered on its own.
- Reading
package-lock.json or pnpm-lock.yaml. A marker changes what is reported, not what is resolved.
- The
update side of the language. Which versions npm and pnpm may move a dependency to is what the declared range says, and that stays the only lever.
Documentation
- The per-type "Markers" answer under "npm and pnpm dependencies", which says the dependency takes none and points at the version-specifier workaround.
- The per-type "Stale dependencies" answer, which would gain the threshold override.
- "Where to put a marker", which says a dependency updated through uv, npm, or pnpm takes no marker.
- A changelog entry under
[Unreleased].
Open questions
- Is the field
"update-time", or npm's "//" convention, or a sidecar file that would serve every format that cannot hold a comment?
- Does a marker naming a dependency cover every section declaring it —
dependencies, devDependencies, and optionalDependencies — or does it have to name the section too?
- If the checks for exactly pinned dependencies are ever added,
yanked and vulnerable stop being redundant here. Should the marker language be shaped for that now, or reported as redundant until then?
- Does npm preserve an unknown field across
npm update and npm pkg set? It should, but the marker's home depends on it.
The problem
Every
package.jsondependency is checked for staleness, and no project can say "yes, this one is old, and we know". The staleness warning is the only check such a dependency gets, and it is the only warning in Update-time that a single reference can neither silence nor put on a threshold of its own.The README's answer does not answer this: "A
package.jsondependency takes no marker, because npm and pnpm update it rather than Update-time rewriting its lines. Opt one out by declaring an upper bound or an exact version instead." An upper bound opts the dependency out of updates, which is a different question. A dependency deliberately kept at a version whose project has gone quiet keeps warning at every run, and the only ways to stop it are to raise--stale-afterfor the whole scan or to disable the check entirely.Every other reference Update-time warns about takes an
ignore[stale]or anignore[stale<DAYS]. This one cannot, for want of somewhere to write it.What the file will accept
package.jsonis strict JSON, so the marker cannot be a comment. Probed 2026-08-15 with the installed npm:package.json// update-time: ignore[stale]on its own linenpm error code EJSONPARSE … package.json must be actual JSON, not just JavaScript"//": "update-time: ignore[stale]"npm pkg getreads the rest of the file back"update-time": { "left-pad": "ignore[stale]" }npm pkg get update-timereturns it andnpm install --package-lock-onlysucceedsA field it is, then, and it has to name the dependency it applies to, since a
package.jsondeclares many.Scope
package.jsondependency is written, and which dependency each one names.stalescope in both its forms:ignore[stale]silences the warning, andignore[stale<90](orallow[stale>=90]) puts that dependency on a threshold of its own.update, a bound, andcooldownsteer an update npm and pnpm make rather than Update-time, andyankedandvulnerablename checks a range-declared dependency does not get.hash-driftis redundant too, since the integrity hashes live in the lock file.The design constraint
Every marker Update-time reads today is found by position: on the reference's own line, or on the line above it. A field-based marker is found by name, so the reference has to be identified rather than located. Reading and validating the directive text is unaffected — that is the
Markerdomain's work and takes a string.Locating the reference itself is already solved:
package_json.dependency_locations()returns each declared dependency with the line of every entry declaring it, which is where the staleness warning is already reported. A name declared in more than one section carries a location per entry, so a marker naming that dependency has to say whether it covers all of them.Out of scope
package-lock.jsonorpnpm-lock.yaml. A marker changes what is reported, not what is resolved.updateside of the language. Which versions npm and pnpm may move a dependency to is what the declared range says, and that stays the only lever.Documentation
[Unreleased].Open questions
"update-time", or npm's"//"convention, or a sidecar file that would serve every format that cannot hold a comment?dependencies,devDependencies, andoptionalDependencies— or does it have to name the section too?yankedandvulnerablestop being redundant here. Should the marker language be shaped for that now, or reported as redundant until then?npm updateandnpm pkg set? It should, but the marker's home depends on it.