From 4385b86bf1a634fff60e774cc3d774321121e52a Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 20 May 2026 10:27:00 -0700 Subject: [PATCH] fix(shell): volumeServer.evacuate no longer panics on a nil volume (#9587) adjustAfterMove now removes the moved volume from the source disk's VolumeInfos in place: it swaps the entry with the last one and nils the tail. evacuateNormalVolumes ranges directly over that same slice, so the niled tail slot is later read as a nil *VolumeInformationMessage and the move attempt panics on vol.DiskType. Iterate over a snapshot of the slice so in-place removals during a move cannot leave nil holes in the loop. --- weed/shell/command_volume_server_evacuate.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/weed/shell/command_volume_server_evacuate.go b/weed/shell/command_volume_server_evacuate.go index cd636e9e8..e8a9b885a 100644 --- a/weed/shell/command_volume_server_evacuate.go +++ b/weed/shell/command_volume_server_evacuate.go @@ -136,7 +136,10 @@ func (c *commandVolumeServerEvacuate) evacuateNormalVolumes(commandEnv *CommandE } } volumeReplicas, _ := collectVolumeReplicaLocations(c.topologyInfo) - for _, vol := range diskInfo.VolumeInfos { + // A successful move calls adjustAfterMove, which removes the volume from + // this disk's VolumeInfos in place. Iterate over a snapshot so removals + // don't leave nil holes in the slice we are ranging over. + for _, vol := range slices.Clone(diskInfo.VolumeInfos) { hasMoved, err := moveAwayOneNormalVolume(commandEnv, volumeReplicas, vol, thisNode, otherNodes, applyChange) if err != nil { fmt.Fprintf(writer, "move away volume %d from %s: %v\n", vol.Id, volumeServer, err)