ITADN

npm: --cached-only fails with "npm package not found in cache" when the cache holds abbreviated metadata without time

#36525Openmagurotuna 创建于 20 天前
M
magurotunacommented
## Summary `--cached-only` fails with a misleading error when the npm cache holds abbreviated install-manifest metadata (written by an older Deno, e.g. 2.8.x), even though the package metadata and contents are fully cached. Since 2.9, the default `minimumDependencyAge` policy (24h) requires publication timestamps, so Deno requests full packuments. A cached abbreviated packument has no per-version `time` data, so Deno decides it must re-fetch the full packument. Under `--cached-only` that network request is forbidden, and instead of falling back to the usable cached metadata it reports: ``` error: Failed loading http://localhost:4260/@denotest%2fesm-basic for package "@denotest/esm-basic" 0: npm package not found in cache: "@denotest/esm-basic", --cached-only is specified. ``` The package *is* in the cache; only the optional publication timestamps are missing. The resolver already treats a missing publish timestamp as acceptable (`matches_newest_dependency_date` fails open), so the cached metadata is fully usable for resolution. This is a backward-compatibility regression: artifacts built and cached with Deno <= 2.8.x deterministically fail to start on 2.9.x with `--cached-only`, before any application code runs (this caused a Deno Deploy incident). ## Reproduction 1. Populate a cache with the abbreviated packument (policy disabled): `deno run --no-lock --minimum-dependency-age=0 main.ts` where `main.ts` contains `import "npm:@denotest/esm-basic";` 2. Simulate a cache written by an older Deno: remove the `time` field (and `_deno.packumentFormat` marker if present) from `<DENO_DIR>/npm/<registry>/@denotest/esm-basic/registry.json` (an unmodified abbreviated cache already lacks both). 3. Run with the default policy and `--cached-only`: `deno run --no-lock --cached-only --minimum-dependency-age=1440 main.ts` Expected: resolves from the cache and prints `ok`. Actual: exits 1 with `npm package not found in cache: "@denotest/esm-basic", --cached-only is specified.` ## Cause In `libs/npm_cache/registry_info.rs`, when cached metadata has empty `time` and no `_deno.packumentFormat` marker, the code falls through to re-fetch the full packument; under `NpmCacheSetting::Only` this then errors instead of returning the cached info: ``` cached metadata lacks timestamps -> prepare to refetch cached_only -> "package not found in cache" ``` "cached metadata + optional upgrade + offline" is incorrectly collapsed into "not cached". ## Suggested fix Only attempt the full-packument re-fetch when networking is permitted (`cache_setting != Only`); otherwise use the cached abbreviated metadata as-is. Online behavior (timestamp enforcement) stays unchanged. A regression spec test (`tests/specs/npm/cached_only_old_abbreviated_metadata`) has been prepared and verified: it fails on current main with the error above and passes with the fix. ## Related issues - #35761 / #35834 — don't re-fetch packuments when the registry provides no `time` data (introduced the `_deno.packumentFormat` marker used in the faulty condition) - #35051 — avoid spurious npm re-resolution that fails under `--cached-only` - #35901 / #35903 — `--cached-only` error when registry info for a deprecated package is missing from the cache (fixed, but only avoids triggering the fetch when it is unnecessary; it doesn't help when resolution from cached metadata is actually needed, which is the case here) - #35285 — slim cached full packument when `minimumDependencyAge` is set - #32364 — request abbreviated packuments from the npm registry (the change that produced the older-format caches) ## Environment - Deno 2.9.x (regression vs 2.8.x caches) - `--cached-only` + default `minimumDependencyAge` (24h)
0 条评论