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

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

Document draft-fossil-sync-protocol-00
Section 8.5.1 — Unversioned-File Synchronisation (client UV upload phase past the output cap); cross-reference §7.3
Type Compatibility note (the draft names one of the two client-sent uvigot forms Fossil produces; no requirement on a conforming implementation changes)
Status Proposed — operator decision pending
Reported 2026-10-11
Submitter Dan Mestas
Found via go-libfossil's sync conformance suite (case sync.8.5.1.no-short-uvigot); reproduced with two fossil 2.28 [52445a27f1] processes, fossil server and fossil uv sync --httptrace with max-upload set to 1

1. Summary

§8.5.1 lists what Fossil's client UV upload step can emit: "a full, mtime-only, or tombstone uvfile, a reference-specific malformed short uvigot, a SHA3 error, or no card", and says the short uvigot is a Fossil source defect that a cleanroom sender MUST NOT emit. That is accurate as far as it goes, and Fossil 2.28 does send the short form. But the same code path also sends a well-formed uvigot NAME MTIME HASH SIZE from the client for every non-tombstone row once the request has reached max-upload. That card is equally wrong-direction (§7.3: uvigot is a server-to-client announcement), draws the same error bad command, and is the more common of the two, since every non-tombstone row takes it. The draft does not mention it, so the MUST NOT reads as covering only the short form.

Fossil is the defective side here; the draft's requirement stands. This note completes the description so that a server implementer expects both forms from Fossil clients and a client implementer does not copy either.

2. Location

3. The divergence

Fossil 2.28, src/xfer.c, send_unversioned_file() (xfer.c:703-760), shared by the server's uvgimme answer (xfer.c:1437) and the client's upload phase (xfer.c:2366):

Observed (--httptrace request and reply files, max-upload 1 on the client, nobody holding oigy on the server):

request 2:  uvigot t.txt 1791754279  0                         (tombstone)
reply 2:    error bad\scommand:\suvigot\st.txt\s1791754279\s\s0\n
request 3:  uvigot v.txt 1791754279 076d3fa1...cd3cf4 6        (new content)
reply 3:    error bad\scommand:\suvigot\sv.txt\s1791754279\s076d3fa1...\s6\n

Each row is removed from the send table after its helper runs, as §8.5.1 says, so neither change reaches the server; fossil uv sync still reports the sync done.

4. Impact

None for a conforming implementation. A server receiving either form from a Fossil client already answers it as an unknown or wrong-direction card (§7.3, §10.1). The note matters for test authors and for client implementers reading §8.5.1 as a description of what to emit: a conformance check that forbids only the short form (four tokens) passes a client that copies Fossil's full-form uvigot.

5. Correction

In §8.5.1, replace the two sentences:

-   full, mtime-only, or tombstone uvfile, a reference-specific malformed
-   short uvigot, a SHA3 error, or no card.  That short uvigot is a
-   Fossil source defect: the server treats it as a wrong-direction
-   request and emits error bad command; a cleanroom sender MUST NOT
-   emit it.
+   full, mtime-only, or tombstone uvfile, a reference-specific uvigot,
+   a SHA3 error, or no card.  The reference client emits that uvigot
+   once the request has reached its upload threshold: the well-formed
+   uvigot NAME MTIME HASH SIZE for a row with content, and a malformed
+   short line with an empty HASH field for a tombstone.  Both are a
+   Fossil source defect: uvigot is server-to-client only (Section 7.3),
+   the server answers either with error bad command, and the row's
+   change is not uploaded in that session.  A cleanroom client MUST NOT
+   send uvigot in either form.

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.