Skip to content

[BUG] :outdated() fails on authenticated / path-prefixed registries: unauthenticated fetch + dropped registry path prefix #1785

Description

@evert

✅ Expected Behavior

vlt query ':workspace > *:outdated(out-of-range)' should list the outdated
dependencies when the configured registry is an authenticated registry with a
path prefix, e.g. https://registry.vlt.io/vltpkg/npm/.

❌ Actual Behavior

Every registry-backed dependency fails. queueNode warns with the full
error-cause chain per node, so a workspace with 131 direct registry deps prints
131 stack traces to stderr and then returns [] on stdout:

Error: Could not retrieve registry versions
    at queueNode2 (…/vlt/chunk-47IR6Z6C.js:6810:7)
    …
  [cause]: {
    name: 'hono',
    cause: Error: Failed to fetch packument
        at retrieveRemoteVersions (…/vlt/chunk-47IR6Z6C.js:6770:11)

There are two independent bugs in
src/query/src/pseudo/outdated.ts,
and fixing either one alone still leaves the selector broken.

1. The request is unauthenticated

retrieveRemoteVersions uses a raw fetch and only sends Accept (the comment
says this is to avoid the RegistryClient disk cache). That also means no
authorization header, so an authenticated registry replies 401!response.ok
Failed to fetch packument. The token is present in the keychain
(~/.local/share/vlt/auth/keychain.json has an entry for
https://registry.vlt.io/vltpkg/npm), it's just never consulted:

$ curl -s -o /dev/null -w '%{http_code}\n' https://registry.vlt.io/vltpkg/npm/hono
401
$ curl -s -o /dev/null -w '%{http_code}\n' -H "authorization: Bearer …" https://registry.vlt.io/vltpkg/npm/hono
200

2. The packument URL drops the registry path prefix

const url = new URL(spec.registry)
url.pathname = `/${node.name}`

Assigning pathname throws away the registry's path prefix, so the request goes
to https://registry.vlt.io/hono instead of
https://registry.vlt.io/vltpkg/npm/hono. With a valid token that URL is a 404,
which the code turns into AbortError('Missing API'):

$ curl -s -o /dev/null -w '%{http_code}\n' -H "authorization: Bearer …" https://registry.vlt.io/hono
404

This is invisible for root-path registries such as registry.npmjs.org, and only
breaks mirrors/proxies served under a prefix.

Not workaroundable via --registry

Passing --registry=https://registry.npmjs.org/ doesn't help: the dep IDs in
vlt-lock.json embed the registry
(~https_c++registry.vlt.io+vltpkg+npm+~@hono+node-server@1.19.17~peer.23) and
hydrate(node.id, …) takes spec.registry from the ID, so the override is
ignored and the same failures occur.

🔄 Steps to Reproduce

  1. In a project whose vlt.json sets
    "config": { "registry": "https://registry.vlt.io/vltpkg/npm/" } (an
    authenticated, path-prefixed registry), run vlt install.
  2. vlt login so a token exists in the keychain for that registry.
  3. Run vlt query ':workspace > *:outdated(out-of-range)'.
  4. Observe one Could not retrieve registry versions stack trace per dependency
    and an empty [] result.

💡 Suggested Fix

  • Build the URL with the existing helpers instead of overwriting pathname
    new URL(name, registryBase(spec.registry)), the idiom already used in
    package-info/src/index.ts
    (const pakuURL = new URL(name, registry)). registryBase /
    normalizeRegistryKey in registry-client/src/auth.ts were added for exactly
    this class of prefixed mirror (see 7ef2692, "security-archive: fix results for
    npm mirrors"); :outdated() never got the same treatment.
  • Send an authorization header. @vltpkg/query is browser-safe (it imports
    @vltpkg/dep-id/browser), so it can't pull in the keychain directly — the
    natural approach is to add a token or a fetchPackument callback to
    ParserState (which already carries signal and retries) and supply it from
    the query command, which has a RegistryClient.
  • Optionally, collapse the per-node warnings into a single summary; one broken
    registry currently produces hundreds of stack traces.

A regression test covering an authenticated registry served under a path prefix
would cover both halves.

🌍 Environment

- OS: linux v24.18.0
- Node: v24.18.0
- vlt: 1.0.2

🔄 Frequency

Always - Happens every time

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugsomething isn't workingclicli specific issuesneeds-triagenew issue that needs triagingqueryanything related to query or the dependency selector syntax

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions