Artifact 05c3f60da713bb1c8375c188bcf6c9a0d4e0772e2b2f577c859efe471f988c2a:
- File docs/rfcs/erratum/sync-protocol-00-s8.5.1-client-uvigot.md — part of check-in [44685f33b1] at 2026-10-12 18:45:05 on branch trunk — Fold the 23 errata into draft-fossil-{artifact-format,repo-state,sync-protocol}-01 (user: dmestas, size: 6238) [annotate] [blame] [check-ins using]
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 | Applied in draft-fossil-sync-protocol-01 (2026-10-12) |
| 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
- §8.5.1 (~lines 1729-1743): "regardless of whether that helper emits a 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."
- For comparison, unchanged: §7.3 (~lines 1293-1306), which describes the same helper on the server side, where both forms are the right direction.
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):
xfer.c:731-737: if the output already holdsmxSendbytes, append"uvigot %s %lld %s %d\n"with the stored hash. For a tombstone the hash is NULL and the field is empty (the short form); otherwise it is a well-formed five-tokenuvigot. The comment says "This only happens on the server side", which is not so: on the clientmxSendismax-upload.xfer.c:1892: the server answers any client-sentuvigotwitherror bad\scommand:\s....
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
- The requirement is unchanged in substance. §7.3 already makes
uvigotserver-to-client; the correction names both forms the reference client sends and extends the explicit MUST NOT to match. - Says what is lost. Stating that the change is not uploaded tells a reader why the defect matters, which the current text leaves implicit.
7. Verification
- Fossil 2.28 [52445a27f1], macOS arm64:
fossil server --localhoston a scratch repository; a clone with one tombstone (fossil uv rm, newer than the server's copy) and one changed file,max-uploadset to 1,fossil uv sync --httptrace. Traced requests carried the short form for the tombstone and the full form for the changed file; both drewerror bad command; the server's unversioned table was unchanged after the sync. - Source references are to
src/xfer.cat tagversion-2.28. - go-libfossil case
sync.8.5.1.no-short-uvigot(requirement SP-8.5.1-7) rejects any client-sentuvigotthat does not have five tokens; under this correction it would reject a client-sentuvigotof any shape.
Prepared against draft-fossil-sync-protocol-00. The RFC remains the oracle; the reference implementation is used only to confirm the observable behavior.