A create on a key the repository already holds overwrites the record instead of failing. The reference PDS refuses it, and clients rely on that to claim a key: knotless creates a repository's dev.knotless.repo record keyed by its name and counts on the create failing when the name is taken.
What happened
On 2026-10-28 a new knotless repository named knotless was created on chadtmiller.com, which already had one. applyWrites#create at dev.knotless.repo/knotless replaced the existing record (Jetstream shows it as an update), pointing the name at an empty repository and orphaning every ref and pack. It was restored by hand from Jetstream's copy of the previous record.
Where
packages/core/src/handlers/xrpc-repo.js, createRecord (~224): "A create whose key the repo already holds overwrites that record, so the tree performs an update."
Same file, applyWrites#create (~620-680): "A create over a key the repo already holds is an update as far as the tree is concerned", then putRecord and an update op.
The comments are right that announcing a create for an overwrite would make an unprovable commit; the fix is to refuse the write, not to turn it into an update.
Expected
As the reference PDS does: a create (by createRecord or applyWrites#create) whose rkey already exists fails with 400 InvalidRequest and writes nothing; in applyWrites, the whole batch fails. Updates stay putRecord / applyWrites#update. putRecord with swapRecord: null already refuses an existing record (~467), which is right.
Tests
createRecord with an existing rkey: 400, record unchanged, no commit.
applyWrites with a #create on an existing rkey among other writes: 400, none applied.
Space applyWrites#create (packages/spaces): check it behaves the same.
A create on a key the repository already holds overwrites the record instead of failing. The reference PDS refuses it, and clients rely on that to claim a key: knotless creates a repository's
dev.knotless.reporecord keyed by its name and counts on the create failing when the name is taken.What happened
On 2026-10-28 a new knotless repository named
knotlesswas created on chadtmiller.com, which already had one.applyWrites#createatdev.knotless.repo/knotlessreplaced the existing record (Jetstream shows it as anupdate), pointing the name at an empty repository and orphaning every ref and pack. It was restored by hand from Jetstream's copy of the previous record.Where
packages/core/src/handlers/xrpc-repo.js,createRecord(~224): "A create whose key the repo already holds overwrites that record, so the tree performs an update."applyWrites#create(~620-680): "A create over a key the repo already holds is an update as far as the tree is concerned", thenputRecordand anupdateop.The comments are right that announcing a
createfor an overwrite would make an unprovable commit; the fix is to refuse the write, not to turn it into an update.Expected
As the reference PDS does: a create (by
createRecordorapplyWrites#create) whose rkey already exists fails with 400InvalidRequestand writes nothing; inapplyWrites, the whole batch fails. Updates stayputRecord/applyWrites#update.putRecordwithswapRecord: nullalready refuses an existing record (~467), which is right.Tests
createRecordwith an existing rkey: 400, record unchanged, no commit.applyWriteswith a#createon an existing rkey among other writes: 400, none applied.applyWrites#create(packages/spaces): check it behaves the same.