@@ -66,7 +66,18 @@ func (q *DeliveryScanQueryByID) QueryByID(ctx context.Context, startingBlock dri
6666 // Keys are supposed to be unique
6767 keys := collections .Keys (evicted ) // These are the state keys we are looking for
6868 ch := make (chan []KeyInfo , len (keys ))
69- go q .queryByID (ctx , keys , ch , startingBlock , evicted )
69+
70+ go func () {
71+ // Defense in depth: any unforeseen panic in this background path must degrade to a
72+ // failed request rather than crashing the whole node process, since nothing else in
73+ // this goroutine's call chain has a recover().
74+ defer func () {
75+ if r := recover (); r != nil {
76+ logger .Errorf ("recovered from panic in queryByID: %v" , r )
77+ }
78+ }()
79+ q .queryByID (ctx , keys , ch , startingBlock , evicted )
80+ }()
7081
7182 return ch , nil
7283}
@@ -117,6 +128,13 @@ func (q *DeliveryScanQueryByID) queryByID(ctx context.Context, keys []driver.PKe
117128
118129 continue
119130 }
131+ if len (values ) != len (keys ) {
132+ logger .Errorf ("peer returned %d values for %d keys in ns [%s]; falling back to block scan" ,
133+ len (values ), len (keys ), ns )
134+ startDelivery = true
135+
136+ continue // treat as a per-namespace failure (=> fall back to the slow block scan)
137+ }
120138 found := make ([]KeyInfo , 0 , len (values ))
121139 var notFound []string
122140 for i , value := range values {
0 commit comments