From 4d06622c01b35390fbe51b7da4908abdc20fc08f Mon Sep 17 00:00:00 2001 From: pingqiu Date: Sun, 29 Mar 2026 23:57:19 -0700 Subject: [PATCH] fix: add nil check for RetainedHistory in sender APIs RecordHandshakeFromHistory and SelectRebuildFromHistory now return an error instead of panicking on nil history input. Co-Authored-By: Claude Opus 4.6 (1M context) --- sw-block/engine/replication/sender.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sw-block/engine/replication/sender.go b/sw-block/engine/replication/sender.go index c88760151..f6b43e359 100644 --- a/sw-block/engine/replication/sender.go +++ b/sw-block/engine/replication/sender.go @@ -272,6 +272,9 @@ func (s *Sender) RecordHandshakeWithOutcome(sessionID uint64, result HandshakeRe // preferred engine-level API — it ensures recovery decisions are backed // by actual retention state, not caller-supplied values. func (s *Sender) RecordHandshakeFromHistory(sessionID uint64, replicaFlushedLSN uint64, history *RetainedHistory) (RecoveryOutcome, *RecoverabilityProof, error) { + if history == nil { + return OutcomeNeedsRebuild, nil, fmt.Errorf("nil RetainedHistory") + } proof := history.ProveRecoverability(replicaFlushedLSN) hr := history.MakeHandshakeResult(replicaFlushedLSN) outcome, err := s.RecordHandshakeWithOutcome(sessionID, hr) @@ -283,6 +286,9 @@ func (s *Sender) RecordHandshakeFromHistory(sessionID uint64, replicaFlushedLSN // the rebuild-source decision accounts for both checkpoint trust AND // tail replayability. func (s *Sender) SelectRebuildFromHistory(sessionID uint64, history *RetainedHistory) error { + if history == nil { + return fmt.Errorf("nil RetainedHistory") + } source, snapLSN := history.RebuildSourceDecision() valid := source == RebuildSnapshotTail return s.SelectRebuildSource(sessionID, snapLSN, valid, history.CommittedLSN)