Skip to content
zit The refusal a fossil client could not read
Login

The refusal a fossil client could not read

A zit server that rejects a request card resets its response and answers with one error card. The sync draft writes two of those answers as prose, error bad command: LINE and error malformed CARD line, and zit emitted that prose word for word: real spaces between the words. The other refusals, auth, clone sequence, sparse origin, content policy, went through the encoder and arrived as the protocol's two tokens. These two did not.

A fossil client tokenizes an error card on the space. Two tokens is an error; four is error malformed followed by two cards it does not know. It reports them as unknown commands, discards the lot, and prints its success summary. On a forge that ran for fifteen hours: every push said Artifacts sent: 94, every push sent the same 94 again, and a fresh clone held none of them. zit push against the same server said "the peer refused" in the same minute, because zit's own client tolerates the malformed card, which is how the bug hid from every test that used zit on both ends.

Fossil's server encodes the text before it writes the card; its source says so in a comment on the emitter. The draft's card grammar says TEXT is encoded too. The prose in two sections describes the text and was read as describing the wire. That is an erratum against the draft's wording; the meaning was never in doubt.

0.3.20 assembles every server error card at one point with its text encoded. The wire texts the draft pins are unchanged; their spaces are \s. A test drives every refusal variant through the emitter and fails on a raw space after the operator, so a new fault cannot reintroduce it. And a stock fossil that hits a zit policy refusal now stops, says why, and exits non-zero, which is the whole point of refusing.

The same release closes a smaller trap: zit remote list saved the word list as the remote. The parser now holds the argument to the http:// or https:// address the help always promised.