Summary #
knot2's upload-pack request classifier treats a request as protocol v2
only when the first pkt-line starts with command=. Clients that send
object-format=sha256 before the command line (Google's Go module proxy
fetch worker does this, running git/2.30.2) get a v0-style response to
their negotiated v2 fetch.
Symptom #
fatal: fetch-pack: protocol error: bad band #78
fatal: remote-curl: bad line length character: PACK
The server sends 0008NAK followed by a raw pack. A v2 client with
sideband-all reads the N of NAK as a sideband byte (0x4e = 78),
and the raw pack bytes land where a pkt-line header belongs.
Reproduction #
Send a fetch request whose first pkt-line is object-format=sha256,
followed by command=fetch, with sideband-all and done. The
response starts with 0008NAK and raw pack bytes instead of
000e\x01packfile band framing. The same request with command=fetch
first gets a fully valid v2 response.
Observed live: go get go.daevix.com/daevix/cmd/dvx@<version> through
the default GOPROXY chain failed with the error above because the Go
module proxy's fetch worker performs the fetch. Fetches with
GOPRIVATE set (which bypass the proxy) and direct git clones all
passed, because those clients send command= first.
Impact #
Every fetch by the Go module proxy's worker against a sha256 knot
fails, which poisons the module's sum.golang.org record and breaks
go get for all users of the vanity import path.
Fix #
Scan the request for the command= line wherever it appears, and
dispatch on the found line. Proposed in the branch
upload-pack-v2-detect with a regression test reproducing the worker's
exact request shape.
Note #
Together with the shallow-boundary fix (#2262, root cause of #769),
this fixes the go vanity URL go get failures end to end: the shallow
bug broke GOPROXY=direct fetches of tagged versions, and this bug
broke every proxied fetch. Both surfaced as the same bad band #78
error, which made diagnosis slow.