Repository navigation
fork_repo / create_repo orphan on-disk repos (and a spent iCaptcha proof / uploaded object) on late DB failure #205
Description
Activity
- addedkind:bugDefect fix — wrong or unsafe behaviorDefect fix — wrong or unsafe behaviorsev:mediumDegraded but workaround existsDegraded but workaround existssubsystem:apiNode REST API request/response surfaceNode REST API request/response surfacesubsystem:attestationCertificates, anchoring, per-ref attestationCertificates, anchoring, per-ref attestationsubsystem:storageBlob/object store, Arweave, IPFS, archivesBlob/object store, Arweave, IPFS, archives
on Jul 15, 2026 Scope update: #196 (commit
8d2fec1) resolved the fork_repo half of this.On a late
create_repofailure, the fork tail now removes the on-disk mirror (repos.rs:1814) and deletes the already-uploaded Tigris archive (repos.rs:1820) before returning, so no row-less disk dir or orphaned object is left. The clone-that-exits-non-zero arm also cleans the mirror now (it previously didn't, which wedged the fork name on retry). Both are covered by RED-verified tests:fork_row_insert_failure_rolls_back_mirror_and_archiveandfork_nonzero_clone_exit_cleans_dest_and_allows_retry.Two things still open here:
-
The non-fork
create_repopath is unchanged (repos.rs:272,state.db.create_repo(&record).await?— still a bare?with noremove_dir_allon the error arm). A transient insert failure afterinit_barestill orphans the freshly-initialized dir with no row; a retry then 500s atinit_bare("repository already exists") whileget_reporeports the name free, wedging it until manual cleanup. This is the remaining work for fork_repo / create_repo orphan on-disk repos (and a spent iCaptcha proof / uploaded object) on late DB failure #205 — mirror the fork remediation onto this path. -
The spent iCaptcha proof on a failed fork is now a deliberate ordering, not an oversight. The proof is consumed before the durable upload, so a failed fork does spend it and a retry needs a fresh proof. I kept that order on purpose: deferring the consume until after the upload would let two requests carrying the same verified proof both pay for a
git clone --mirrorbefore one loses the consume race. If you'd still rather make the recovery idempotent (so a retry reuses the proof), that's a real option — flagging it as a design call rather than a straight bug.
Suggest narrowing this issue to item 1 (the non-fork
create_repodisk orphan).-
- addedcrate:nodegitlawb-node — the serving node and REST APIgitlawb-node — the serving node and REST API
on Sep 5, 2026
Surfaced during review of #196 (pre-existing ordering; not in that PR's diff).
fork_repo ordering (api/repos.rs:1555 -> 1567 -> 1585 -> 1605): spend proof ->
git clone --mirrorto disk ->release_after_write(Tigris upload) ->db.create_repo. Ifcreate_repofails, the on-disk mirror and the already-uploaded Tigris object are left with no DB row, and the single-use iCaptcha proof is already consumed.create_repo (api/repos.rs:208 -> 210-219 -> 236):
proof.consumethenrepo_store.init(blockinggit init) run beforedb.create_repo; a DB failure orphans the freshly-initialized directory. No cleanup-on-failure exists on either path.Fix direction: make disk materialization + proof spend adjacent to a guaranteed-successful DB write; on
db.create_repofailure best-effortremove_dir_all(disk_path), and prefer deferring the Tigris upload until after the row commits. Verified by tracing the ordering during the #196 review.