kovidgoyal/kitty · error

Cannot call CreateDelta() before loading a signature

Error message

Cannot call CreateDelta() before loading a signature

What it means

CreateDelta requires a signature to have been loaded first. FinishSignatureData succeeded but self.signature is nil, meaning header-only data with zero blocks was processed, so there is nothing to diff against.

Source

Thrown at tools/rsync/api.go:236

			return io.EOF
		case nil:
			bl.Serialize(b[:BlockHashSize])
			_, err = output.Write(b[:BlockHashSize])
			return err
		default:
			return err
		}
	}
}

// Create a serialized delta based on the previously loaded signature
func (self *Differ) CreateDelta(src io.Reader, output io.Writer) func() error {
	if err := self.FinishSignatureData(); err != nil {
		return func() error { return err }
	}
	if self.signature == nil {
		return func() error {
			return fmt.Errorf("Cannot call CreateDelta() before loading a signature")
		}
	}
	return self.rsync.CreateDiff(src, self.signature, output)
}

func (self *Differ) BlockSize() int {
	return self.rsync.BlockSize
}

// Add more external signature data
func (self *Differ) AddSignatureData(data []byte) (err error) {
	self.unconsumed_signature_data = append(self.unconsumed_signature_data, data...)
	if !self.rsync.HasHasher() {
		consumed, err := self.read_signature_header(self.unconsumed_signature_data)
		if err != nil {
			if consumed < 0 {
				return nil
			}

View on GitHub (pinned to 6d5d0c4406)

Solutions

  1. Generate a real signature from a non-empty source before creating a delta
  2. Handle the empty-source case separately rather than calling CreateDelta
  3. Verify AddSignatureData received block data, not just the header
Defensive patterns

Strategy: validation

Validate before calling

if differ.BlockSize() == 0 || signatureBlockCount == 0 { skip CreateDelta; nothing to diff }

Type guard

func canCreateDelta(d *rsync.Differ) bool { return d.BlockSize() > 0 }

Prevention

When it happens

Trigger: Calling CreateDelta after AddSignatureData consumed only a valid header (empty file signature) — signature slice stays nil — or calling CreateDelta before any signature data at all on a path where FinishSignatureData passes.

Common situations: Diffing against an empty source whose signature contains only the header, or API misuse where CreateDelta is called without a prior signature load.

Related errors


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