block / block/buzz

git-credential-nostr: first push of any pack > 1 MiB fails (401 challenge on a streamed, non-replayable POST)

Open
#4,195 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

# git-credential-nostr: first push of any pack > 1 MiB fails (401 challenge on a streamed, non-replayable POST)

## Summary

Out of the box, pushing more than ~1 MiB to Buzz git dies with:

```
error: RPC failed; HTTP 401 curl 56 The requested URL returned error: 401
send-pack: unexpected disconnect while reading sideband packet
fatal: the remote end hung up unexpectedly
Everything up-to-date ← misleading: nothing was pushed
```

## Mechanism

Three correct-in-isolation behaviors compose into a guaranteed failure:

1. `git-credential-nostr` returns `ephemeral=true`, so git caches nothing and sends the `git-receive-pack` POST **unauthenticated first**, expecting to retry after the 401 challenge.
2. The Buzz server (correctly) answers the unauthenticated POST with 401.
3. git can only replay a challenged POST if the body is buffered; packs larger than `http.postBuffer` (default **1 MiB**) are streamed chunked and cannot be replayed → hard failure.

So the failure threshold is exactly `http.postBuffer`, and the very first real-world push (any repo with more than trivial history) hits it. Small pushes work, which makes this look like flaky infrastructure rather than a deterministic composition bug.

## Workaround (verified)

```bash
git config http.postBuffer 524288000 # buffer the pack so the 401 retry can replay it
```

After this a 90 MB pack pushes fine (the ±60s NIP-98 window is not a problem — the token is minted at challenge time, after the buffered body is ready).

## Suggested fixes (in increasing order of effort)

1. **Document it.** A "Large pushes" section in `crates/git-credential-nostr/README.md` with the `http.postBuffer` line would eliminate the trap for near-zero cost. The README's troubleshooting table already covers subtler failures than this one.
2. **Pre-emptive auth.** The helper already knows the server's auth scheme after the first `info/refs` challenge of the session. Returning a credential git can send pre-emptively on the subsequent POST (i.e., not marking it `ephemeral` within a single git invocation, scoped by the ±60s validity) avoids the challenge round-trip entirely for the push POST.
3. **Server-side `Expect: 100-continue` handling** so the 401 lands before the body is transmitted; git/curl then retries with auth without needing a replayable body. (Most invasive; 1–2 make it unnecessary.)

## Environment

Relay at `63496cc1d`, git 2.50.1, `git-credential-nostr` built from the same tree; observed 2026-08-01 mirroring a 101 MB repository.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.