Skip to content

/pr/ endpoint cannot resolve PR-number refs since pkg.pr.new v0.0.67 (no more 302s to scrape) #1348

@khandrew1

Description

@khandrew1

Summary

Every /pr/<owner>/<repo>@<PR-number>/... URL has returned 404 pkg.pr.new: tag or branch not found since around April 26–27, 2026, when pkg.pr.new shipped v0.0.67. Commit-SHA refs (@<sha>) still work.

Reproduction

$ curl -sI "https://esm.sh/pr/mcp-use/mcp-use@1404/server" | head -1
HTTP/2 404
$ curl -s  "https://esm.sh/pr/mcp-use/mcp-use@1404/server"
pkg.pr.new: tag or branch not found

# Same with --compact form, same with any other repo:
$ curl -s "https://esm.sh/pr/tinylibs/tinybench/tinybench@1"        # → 404 same
$ curl -s "https://esm.sh/pr/vitest-dev/vitest/vitest@9000"         # → 404 same
$ curl -s "https://esm.sh/pr/honojs/hono/hono@4500"                 # → 404 same

# SHA refs still resolve fine:
$ curl -sI "https://esm.sh/pr/mcp-use/mcp-use@dffcf42/server" | head -1
HTTP/2 200

For context, the upstream tarball is reachable directly:

$ curl -sI "https://pkg.pr.new/mcp-use@1404"
HTTP/2 200
content-type: application/tar+gzip
x-commit-key: mcp-use:mcp-use:dffcf42d399d18d19ac0ca766e60b0ef13309181

So pkg.pr.new is healthy — only esm.sh's resolution path is broken.

Root cause

resolvePrPackageVersion in server/path.go (link) maps PR-number / branch / tag refs to a commit SHA by relying entirely on http.Client.CheckRedirect to scan redirect URLs for a hex-suffixed path:

versionRegex := regexp.MustCompile(`[^/]@([\da-f]{7,})$`)
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
    match := versionRegex.FindStringSubmatch(req.URL.Path)
    if len(match) > 1 {
        version = match[1][:7]
    }
    ...
}
_, err = client.Fetch(u, nil)

Then parseEsmPath rejects anything that isn't already commitish:

esm.PkgVersion, err = resolvePrPackageVersion(esm)
...
if !isCommitish(esm.PkgVersion) {
    err = errors.New("pkg.pr.new: tag or branch not found")
}

This worked because pkg.pr.new used to 302 from /<pkg>@<N> through URLs ending in @<sha> before delivering the tarball, so the CheckRedirect hook would capture the SHA along the way.

In stackblitz-labs/pkg.pr.new#468"refactor: unify tarball resolution and optimize download latency" — the maintainers replaced that redirect chain with a single tarball-resolver middleware that returns the tarball directly with HTTP 200. The PR description explicitly says: "Remove 302 redirects. Eliminate routing hacks required to prevent Nitro from hijacking Vue's / and /~/... routes."

That refactor shipped in v0.0.67 on 2026-04-26. Since then, esm.sh's CheckRedirect callback never fires for PR-number lookups, version stays as the original PR number, isCommitish returns false, and the resolver errors out with tag or branch not found. SHA refs short-circuit on if isCommitish(esm.PkgVersion) earlier in parseEsmPath, which is why they're unaffected.

Suggested fix

The same PR #468 added two response headers specifically to make tarball resolution machine-readable:

x-commit-key: <owner>:<repo>:<full-sha>
x-pkg-name-key: <pkg-name>

Switching resolvePrPackageVersion to read x-commit-key from the response is a small, robust fix that stays within pkg.pr.new and avoids depending on undocumented redirect behavior:

resp, err := client.Fetch(u, nil)
if err == nil {
    if key := resp.Header.Get("x-commit-key"); key != "" {
        // x-commit-key format: "<owner>:<repo>:<full-sha>"
        if idx := strings.LastIndex(key, ":"); idx >= 0 && len(key)-idx-1 >= 7 {
            version = key[idx+1:][:7]
        }
    }
}

Impact

  • Every CI pipeline and consumer using https://esm.sh/pr/<owner>/<repo>@<PR-number>/... is currently broken.
  • Workaround in user CI: switch to the commit-SHA form (@<sha>), which still works.

Happy to send a PR if a maintainer can confirm the preferred approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions