microsoft/garnet · error · Exception
Invalid SETSLOT Operation
Error message
Invalid SETSLOT Operation
What it means
Thrown by MigrationDriver when mapping a MigrateState to the byte sequence sent via CLUSTER SETSLOTRANGE. Only IMPORT, STABLE, and NODE are valid SETSLOT states; SUCCESS, FAIL, PENDING (and invalid casts) are rejected. It protects the wire protocol from emitting an undefined SETSLOT opcode.
Source
Thrown at libs/cluster/Server/Migration/MigrationDriver.cs:34
/// <param name="state"></param>
/// <returns></returns>
public async Task<bool> TrySetSlotRangesAsync(string nodeid, MigrateState state)
{
var client = migrateOperation[0].Client;
try
{
if (!await CheckConnectionAsync(client).ConfigureAwait(false))
{
Status = MigrateState.FAIL;
return false;
}
var stateBytes = state switch
{
MigrateState.IMPORT => IMPORTING,
MigrateState.STABLE => STABLE,
MigrateState.NODE => NODE,
_ => throw new Exception("Invalid SETSLOT Operation"),
};
logger?.LogTrace("Sending CLUSTER SETSLOTRANGE {state} {nodeid} {slots}", state, nodeid ?? "null", ClusterManager.GetRange([.. _sslots]));
var result = await client.SetSlotRange(stateBytes, nodeid, _slotRanges)
.WaitAsync(_timeout, _cts.Token).ConfigureAwait(false);
// Check if setslotsrange executed correctly
if (!result.Equals("OK", StringComparison.Ordinal))
{
logger?.LogError("SetSlotRange error: {error}", result);
Status = MigrateState.FAIL;
return false;
}
logger?.LogTrace("[Completed] SETSLOT {slots} {state} {nodeid}", ClusterManager.GetRange([.. _sslots]), state, nodeid ?? "");
return true;
}View on GitHub (pinned to 951b0fc683)
Solutions
- Pass only MigrateState.IMPORT, MigrateState.STABLE, or MigrateState.NODE to the slot-range setter.
- Separate progress/result states from slot-config states at the call site to prevent the mix-up.
- Add a Debug.Assert on the incoming state before the switch.
Example fix
// before
var stateBytes = state switch
{
MigrateState.IMPORT => IMPORTING,
MigrateState.STABLE => STABLE,
MigrateState.NODE => NODE,
_ => throw new Exception("Invalid SETSLOT Operation"),
};
// after
Debug.Assert(state is MigrateState.IMPORT or MigrateState.STABLE or MigrateState.NODE);
var stateBytes = state switch
{
MigrateState.IMPORT => IMPORTING,
MigrateState.STABLE => STABLE,
MigrateState.NODE => NODE,
}; Defensive patterns
Strategy: validation
Validate before calling
// Validate slot-config state before SETSLOTRANGE
if (state is not (MigrateState.IMPORT or MigrateState.STABLE or MigrateState.NODE))
throw new ArgumentOutOfRangeException(nameof(state), state, "State must be IMPORT, STABLE, or NODE"); Prevention
- Keep progress/result states (SUCCESS/FAIL/PENDING) strictly separate from slot-config states at call sites.
- Add a Debug.Assert on the incoming state before the switch.
- Unit-test the slot-state setter only accepts the three valid opcodes.
When it happens
Trigger: Calling the SETSLOT-range sender with state set to SUCCESS, FAIL, PENDING, or an out-of-range value instead of one of the three valid slot-configuration states.
Common situations: A migration driver caller passes a result/progress state (SUCCESS/FAIL/PENDING) where a slot-state (IMPORT/STABLE/NODE) is expected, due to mixing up the two roles of the MigrateState enum.
Related errors
- MigrateSession Invalid TransferOption {transferOption}
- Invalid KeyMigrationStatus: {state}
- invalid failover status
- Sketch size should be power of 2!
- Option {fileType} not supported
AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13).
Data as JSON: /api/errors/72e329bbe4c8826e.
Report an issue: GitHub.