fangorn/ex_git_objectstore
public
UploadPackV2: git fetch fails with 'expected no other sections to be sent after no ready' #27
Links
No links yet.
Problem
git fetch against a repo served by UploadPackV2 fails when the client’s local history is unrelated to what’s on the server:
fatal: expected no other sections to be sent after no 'ready'
Reproduced against fangorn/hephaestus on 2026-04-18 — a local git fetch errors out because the client sent have lines that don’t match any object on the server.
Root cause
handle_fetch/2 calls build_acknowledgments/2 without passing whether the client sent done. When the client sends done + haves but none match, the server emits:
0014acknowledgments
0008NAK
0001000dpackfile
...<sideband>...
0000
Per protocol v2 (Documentation/technical/protocol-v2.txt):
acknowledgments = PKT-LINE(\"acknowledgments\" LF)
(nak | *ack)
[ready]
and:
If the server has found a common base commit, or the client has sent a
doneline, the server will sendreadyfollowed by thepackfilesection.
So: once done is in the request, the acks section must either end with ready or be omitted entirely. Sending NAK followed by a packfile is a protocol violation, and real git clients reject it with the error above.
Fix
- Parse
donefrom the fetch args. done+ no matching haves → omit the acks section (packfile sent unconditionally).done+ some ACKs → emitACK … / ready / delim.- No
done(multi-round negotiation) → emitNAK / flushorACK … / flush; client sends another round.
Tests
- Unit:
test/ex_git_objectstore/protocol/upload_pack_v2_test.exs— state-machine assertions for the protocol v2 ack/ready invariant. - Interop:
test/ex_git_objectstore/integration/upload_pack_v2_git_client_test.exs— spins up a minimalgit://TCP daemon and drivesgit clone/git fetchagainstUploadPackV2with a realgitCLI. Includes the hephaestus regression scenario.