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.
Summary
Every
/pr/<owner>/<repo>@<PR-number>/...URL has returned404 pkg.pr.new: tag or branch not foundsince around April 26–27, 2026, when pkg.pr.new shipped v0.0.67. Commit-SHA refs (@<sha>) still work.Reproduction
For context, the upstream tarball is reachable directly:
So pkg.pr.new is healthy — only esm.sh's resolution path is broken.
Root cause
resolvePrPackageVersioninserver/path.go(link) maps PR-number / branch / tag refs to a commit SHA by relying entirely onhttp.Client.CheckRedirectto scan redirect URLs for a hex-suffixed path:Then
parseEsmPathrejects anything that isn't already commitish:This worked because pkg.pr.new used to 302 from
/<pkg>@<N>through URLs ending in@<sha>before delivering the tarball, so theCheckRedirecthook 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-resolvermiddleware 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
CheckRedirectcallback never fires for PR-number lookups,versionstays as the original PR number,isCommitishreturns false, and the resolver errors out withtag or branch not found. SHA refs short-circuit onif isCommitish(esm.PkgVersion)earlier inparseEsmPath, which is why they're unaffected.Suggested fix
The same PR #468 added two response headers specifically to make tarball resolution machine-readable:
Switching
resolvePrPackageVersionto readx-commit-keyfrom the response is a small, robust fix that stays within pkg.pr.new and avoids depending on undocumented redirect behavior:Impact
https://esm.sh/pr/<owner>/<repo>@<PR-number>/...is currently broken.@<sha>), which still works.Happy to send a PR if a maintainer can confirm the preferred approach.