Skip to content
zit Erratum — draft-fossil-sync-protocol-00 §3.3
Login

Erratum — draft-fossil-sync-protocol-00 §3.3

Document draft-fossil-sync-protocol-00
Section 3.3 — Phantom Record Lifecycle (peer-lacks filter on the client); 8.8 — Gimme Eligibility Filters
Type Compatibility note (Fossil's client discards peer-lacks before it is used; the draft's rule is kept)
Status Applied in draft-fossil-sync-protocol-01 (2026-10-12)
Reported 2026-10-11
Submitter Dan Mestas
Found via go-libfossil's conformance suite against Fossil 2.28 (scope note SP-3.3-3); confirmed by reading Fossil's source and by running a Fossil client against a scripted peer

1. Summary

§3.3 says the phantom scan excludes peer-lacks hashes, the hashes the peer just asked for with gimme. Fossil's server applies that filter within a request. Fossil's client records peer-lacks while reading a reply and then drops the table before its next phantom scan, so its next request asks the peer again for a hash the peer has just said it lacks.

2. Location

§3.3 (~lines 516-530):

Each round, peer-has records hashes announced or successfully sent by the peer; peer-lacks records gimme requests. … The ordinary phantom scan excludes peer-lacks hashes, …

and the reply-processing table (~line 412): gimme: add peer-lacks; ….

3. The divergence

Source, Fossil 2.28 (src/xfer.c):

The client's remote_unk() call has no other reader, so its intent is the draft's rule; the table's lifetime defeats it.

Run: a scripted HTTP peer answered a fossil pull from an empty repository with igot U and gimme U in one reply (U = 01256859…, absent). Fossil made U a phantom, went a second round, and its second request contained gimme 01256859….

4. Impact

Harmless, but visible.

5. Correction

Keep the rule. Note Fossil's client after the filter sentence in §3.3:

    The ordinary phantom scan excludes peer-lacks hashes, names in the
    repository shun table, and private hashes unless private sync is
    enabled; shun-sha1 does not itself suppress an otherwise eligible
    gimme.
+   (Fossil's client discards the peer-lacks it records from a reply
+   before building the next request, so it may repeat gimme for a hash
+   the peer has just requested.  Receivers already skip a gimme for
+   absent content silently; no further handling is needed.)

Alternative, which needs the operator's decision: propose that Fossil keep unk across the cycle boundary in client_sync() (create it once before the loop and drop it after). Filing that is a separate decision from this erratum.

6. Rationale

7. Verification


Prepared against draft-fossil-sync-protocol-00. The RFC remains the oracle; the reference implementation is used only to confirm the observable behavior.