kovidgoyal/kitty · error

Invalid weak_hash in signature header: %d

Error message

Invalid weak_hash in signature header: %d

What it means

The rsync signature header stores a weak-hash algorithm id at bytes 6-7; read_signature_header accepts only Rsync. Any other id means the signature was produced with an incompatible or corrupt hash configuration.

Source

Thrown at tools/rsync/api.go:96

	switch csum := ChecksumType(bin.Uint16(data[2:])); csum {
	case XXH3128Sum:
		self.Checksum_type = XXH3128Sum
		self.rsync.SetChecksummer(new_xxh3_128)
	default:
		return consumed, fmt.Errorf("Invalid checksum_type in signature header: %d", csum)
	}
	switch strong_hash := StrongHashType(bin.Uint16(data[4:])); strong_hash {
	case XXH3:
		self.Strong_hash_type = strong_hash
		self.rsync.SetHasher(new_xxh3_64)
	default:
		return consumed, fmt.Errorf("Invalid strong_hash in signature header: %d", strong_hash)
	}
	switch weak_hash := WeakHashType(bin.Uint16(data[6:])); weak_hash {
	case Rsync:
		self.Weak_hash_type = weak_hash
	default:
		return consumed, fmt.Errorf("Invalid weak_hash in signature header: %d", weak_hash)
	}
	block_size := int(bin.Uint32(data[8:]))
	consumed = 12
	if block_size == 0 {
		return consumed, fmt.Errorf("rsync signature header has zero block size")
	}
	if block_size > MaxBlockSize {
		return consumed, fmt.Errorf("rsync signature header has too large block size %d > %d", block_size, MaxBlockSize)
	}
	self.rsync.BlockSize = block_size
	self.signature = make([]BlockHash, 0, 1024)
	return
}

func (self *Api) read_signature_blocks(data []byte) (consumed int) {
	block_hash_size := self.rsync.HashSize() + 12
	for ; len(data) >= block_hash_size; data = data[block_hash_size:] {
		bl := BlockHash{}

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Ensure both ends use the same kitty/rsync tool version and hash settings
  2. Verify the byte stream starts exactly at the signature header
  3. Regenerate the signature on the source side and retry the transfer
Defensive patterns

Strategy: try-catch

Validate before calling

if len(data) < 8 { return fmt.Errorf("signature data too short") }
wh := binary.BigEndian.Uint16(data[6:8])
if wh != uint16(rsync.Rsync) { return fmt.Errorf("unsupported weak hash %d", wh) }

Try / catch

if err := differ.AddSignatureData(buf); err != nil { log.Printf("signature rejected: %v", err); return err }

Prevention

When it happens

Trigger: Feeding AddSignatureData bytes whose header weak_hash field is not the Rsync id — typically a truncated/garbled stream or a signature generated by a different implementation/version.

Common situations: Protocol version mismatch between differ and patcher, byte-stream corruption, or accidentally prepending extra bytes before the signature.

Related errors


AI-assisted analysis of kovidgoyal/kitty@6d5d0c4406 (2026-08-27). Data as JSON: /api/errors/1c008c4264cf3652. Report an issue: GitHub.