Skip to content

fix(publish): survive npm tarball lag and slow Rekor - #267

Merged
BleedingDev merged 3 commits into
main-ultramodernfrom
fix/publish-tarball-propagation-20261029
Oct 29, 2026
Merged

BleedingDev merged 3 commits into
main-ultramodernfrom
fix/publish-tarball-propagation-20261029

Conversation

@BleedingDev

@BleedingDev BleedingDev commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Why the change

Cohort 3.9.3-ultramodern.14 stopped six times while publishing. npm briefly listed versions whose tarballs still answered 404, and Sigstore gave Rekor only 5 seconds, so a slow Rekor turned each server-runtime publish into a fatal "409 equivalent entry already exists".

Special things to note

  • The 409 is self-inflicted. npm's bundled sigstore uses DEFAULT_TIMEOUT = 5000 and fetchOnConflict: false. Rekor logged the entry 2 seconds into the try, answered after the client gave up, and the client's own retry then hit 409. libnpmpublish passes its options to sigstore.attest, so timeout: 300000 (npm-registry-fetch's own default) reaches Rekor and Fulcio.
  • Only transient failures are retried: tarball 404/429/5xx or a failed request, and the existing transient publish patterns. A byte mismatch, 403 or any other error still fails at once.
  • Once this merges, .14 finishes with a recovery run (recovery_run_id=40881100403, attempt 1). It reuses the accepted bundle and the 34 packages already on npm.

Change outline

 publishPackageBuffer -> libnpmpublish.publish(opts) -> sigstore.attest(opts)
-  Rekor timeout 5s, retries 2, no fetch on conflict -> 409 on its own entry
+  timeout: 300000                                   -> waits like the registry PUT
 publishPackage retry
-  3 attempts, 15s apart
+  6 attempts, 15s / 30s / 45s / 60s / 75s apart
 verifyRegistryTarball(item, dist, fetch, wait = sleep)
   packument lists .14, tarball not served yet
-  HTTP 404 -> "Registry publish preflight failed"
+  404 / 429 / 5xx / request error -> retry, 8 attempts x 15s
   byte mismatch, 403, other       -> fail immediately

What run 40881100403 hit:

attempt 2, 3, 5   tarball 404 on tsconfig, renderer-core, plugin right after they published
attempt 1, 4, 6   tlog 409: render once, then server-runtime 6/6 tries
rekor entry       integrated 14:24:13, 2s into try 3

Validation:

test:publish-tooling   411/411
new tests              tarball 404->503->429->200 verifies, 8x404 rejects, 403 rejects at once
                       publish 5x tlog 409 then success; 6x409 rejects; E403 fails at once
                       publishPackageBuffer passes timeout 300000 with provenance

🤖 Generated with Claude Code

npm can list a freshly published version, and even move `latest` to it,
before its tarball URL stops answering 404. The publish preflight treated
that as a hard failure, so cohort 3.9.3-ultramodern.14 stopped twice on
`tsconfig` and `renderer-core` until the registry caught up. A 404, 429 or
5xx tarball response is now retried for about two minutes; a byte
mismatch or any other status still fails at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Rsdoctor Bundle Diff Analysis

📊 Quick Summary
Project Total Size Gzip Size Change Gzip Change
bundle-diff 533.8 KB 173.0 KB 0 0

Generated by Rsdoctor GitHub Action

UltraModern Debug and others added 2 commits October 29, 2026 15:15
When Rekor answers slowly, the Sigstore client retries an entry it already
logged and fails with "409 an equivalent entry already exists" before npm
sees the publish. Three attempts 15 seconds apart were not enough during
the 3.9.3-ultramodern.14 publication. Six attempts now wait 15, 30, 45, 60
and 75 seconds; each attempt signs afresh, and non-transient errors still
fail at once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
libnpmpublish passes its options to sigstore.attest, and sigstore gives
Rekor 5 seconds by default without fetching an entry on conflict. During
3.9.3-ultramodern.14, Rekor logged server-runtime's entry two seconds into
a try but answered after the client gave up, so its own retry hit
"409 an equivalent entry already exists" on all six tries across two
runs. Publishing now passes timeout: 300000, npm-registry-fetch's own
default, so signing waits as long as the registry upload does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BleedingDev BleedingDev changed the title fix(publish): wait for npm to serve a listed tarball fix(publish): survive npm tarball lag and slow Rekor Oct 29, 2026
@BleedingDev
BleedingDev merged commit 281fd86 into main-ultramodern Oct 29, 2026
70 checks passed
@BleedingDev
BleedingDev deleted the fix/publish-tarball-propagation-20261029 branch October 29, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant