Skip to content

Relay never seeds git repos on kind:30617 announce — repos stay 404 "repository not found" indefinitely #3527

Closed

Description

@jackjackbits

Summary

On the hosted relay permissionless.communities.buzz.xyz (NIP-11 reports software: https://github.com/block/buzz, version: 0.2.0), announcing a repo via kind:30617 is accepted and stored, but the git smart-HTTP endpoint never becomes available. GET /git/<owner-hex>/<repo-id>/info/refs?service=git-upload-pack (and git-receive-pack) returns 404 repository not found indefinitely, so the repo can never be pushed to or cloned.

Per current source, announce is the only provisioning path: handle_git_repo_announcement in crates/buzz-relay/src/handlers/side_effects.rs reserves the name in Postgres and seeds the empty-manifest pointer that info_refs requires (crates/buzz-relay/src/api/git/transport.rs — Ok(None) → 404). The git router exposes only info/refs, git-upload-pack, git-receive-pack, so there is no other way to create a repo.

Reproduction (all requests NIP-98/Nostr-authenticated; unauthenticated requests correctly 401)

  1. Publish kind:30617 with d=<repo-id> and a clone URL https://permissionless.communities.buzz.xyz/git/<owner-hex>/<repo-id>. Event is accepted ({"accepted":true}) and retrievable.
  2. GET /git/<owner-hex>/<repo-id>/info/refs?service=git-upload-pack with valid signed auth → 404 repository not found, still true 2+ hours later.
  3. Same-owner re-announce — which per the code comments "ensures the pointer rather than assuming it" — is accepted but the endpoint still 404s. This rules out a one-time race; the seed side effect is not taking effect at all.
  4. Reproduced with three separate identities/repos on this relay, including the community owner's key.

Why it is silent

ingest.rs treats side effects as best-effort: if let Err(e) = handle_side_effects(...) { warn!(..., "Side effect failed: {e}") } — the announcement is stored even when seeding fails, and the underlying error (object-store put, missing git_repo_names migration, etc.) exists only in relay server logs. Clients cannot distinguish "seeded" from "seed silently failed".

Relay operators: please check server logs for Side effect failed on kind 30617 on this deployment. If the deployed build predates the seeding feature, a redeploy may be all that is needed.

Suggested improvements

  • Surface seed failures to the announcing client (reject the 30617, or include a warning in the OK message) instead of storing an announcement for a repo that can never exist.
  • Consider a health/status probe for the git store so operators notice storage misconfiguration before users hit 404s.

Activity

  1. tlongwell-block commented on Jul 29, 2026

    @tlongwell-block
    Collaborator

    Fix is up: #3626.

    What you hit: repos announced with vanilla NIP-34 (no buzz-channel tag on the kind:30617) have no channel-membership ACL, so the SEC-005 read gate denies every fetch with a bare 404 — forever, with no hint why.

    What the fix does:

    • You'll now get told. Fetching your own unbound repo returns the same 404 status, but the body says exactly how to fix it: buzz repos bind --id <repo> --channel <channel-uuid>. Pushes get the same guidance.
    • New buzz repos bind command rebinds an existing announcement to a channel without re-announcing. buzz repos create also gains --channel.
    • Desktop surfaces the same remediation in its branch/merge dialogs.

    Until it lands, the workaround is to re-publish your 30617 with a buzz-channel tag pointing at a channel you're a member of.

  2. added a commit that references this issue on Jul 30, 2026
    788b3c0
  3. jackjackbits commented on Jul 30, 2026

    @jackjackbits
    Author
  4. jackjackbits commented on Jul 30, 2026

    @jackjackbits
    Author

    Thanks — confirming the channel-binding workaround works on the deployed relay (fresh 30617 with a buzz-channel tag → endpoint serves immediately). But applying it to the original repo surfaced a second silent-failure mode, this time in the name registry.

    git_repo_names reservations are never released, and cross-owner collisions are invisible to the author.

    Sequence that produced it (community permissionless.communities.buzz.xyz):

    1. 2026-07-23: agent key 9559ef56… announced bitchat (vanilla NIP-34, no buzz-channel). Per the fixed understanding, this seeded fine — it was only unreadable due to the missing binding. Crucially it also reserved the name.
    2. The repo owner 82341f88… later announced bitchat under their own key — including a re-announce with the buzz-channel tag after your fix guidance. handle_git_repo_announcement rejects it ("repo name 'bitchat' already taken by another owner"), but ingest stores the event and only logs a warning, so from the author's side the announcement is accepted and the endpoint 404s forever. Same UX black hole as the original report, different cause.
    3. 9559ef56… published a NIP-09 kind:5 a-tag deletion of its 30617. handle_a_tag_deletion takes the generic NIP-33 branch and soft-deletes the event row only — the git_repo_names row is untouched. There is no user-facing way to release a name.

    Empirical confirmation: after the deletion, a fresh announce of bitchat by 82341f88… (with channel tag) still 404s, while a re-announce by 9559ef56… (with channel tag) makes /git/9559ef56…/bitchat serve immediately → the reservation is stranded with the deleted announcement's key.

    Asks:

    1. Operational: release the bitchat reservation held by 9559ef56… so 82341f88… can claim it. Not urgent — both keys belong to the same human/agent pair and we have a working repo under the agent key meanwhile (the managed-agent-owner push-authority path works nicely, for what it's worth).
    2. Code: release the reservation when the owning announcement is kind:5-deleted (or add an explicit release), and surface cross-owner collisions to the author (OK=false or remediation text) instead of warn-and-continue.

    Minor client-interop note while we're here: pushes with packs >1MB fail with RPC failed; HTTP 401 because git streams them chunked and can't replay the body for the NIP-98 challenge dance; http.postBuffer=500m works around it. Might be worth a line in the docs next to the credential-helper setup.

  5. added a commit that references this issue on Aug 3, 2026
    135b071
  6. added a commit that references this issue on Aug 23, 2026
    ca40fdf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions