{"record":{"id":"72e329bbe4c8826e","repo":"microsoft/garnet","slug":"invalid-setslot-operation","errorCode":null,"errorMessage":"Invalid SETSLOT Operation","messagePattern":"Invalid SETSLOT Operation","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"libs/cluster/Server/Migration/MigrationDriver.cs","lineNumber":34,"sourceCode":"        /// <param name=\"state\"></param>\n        /// <returns></returns>\n        public async Task<bool> TrySetSlotRangesAsync(string nodeid, MigrateState state)\n        {\n            var client = migrateOperation[0].Client;\n            try\n            {\n                if (!await CheckConnectionAsync(client).ConfigureAwait(false))\n                {\n                    Status = MigrateState.FAIL;\n                    return false;\n                }\n\n                var stateBytes = state switch\n                {\n                    MigrateState.IMPORT => IMPORTING,\n                    MigrateState.STABLE => STABLE,\n                    MigrateState.NODE => NODE,\n                    _ => throw new Exception(\"Invalid SETSLOT Operation\"),\n                };\n\n                logger?.LogTrace(\"Sending CLUSTER SETSLOTRANGE {state} {nodeid} {slots}\", state, nodeid ?? \"null\", ClusterManager.GetRange([.. _sslots]));\n\n                var result = await client.SetSlotRange(stateBytes, nodeid, _slotRanges)\n                    .WaitAsync(_timeout, _cts.Token).ConfigureAwait(false);\n\n                // Check if setslotsrange executed correctly\n                if (!result.Equals(\"OK\", StringComparison.Ordinal))\n                {\n                    logger?.LogError(\"SetSlotRange error: {error}\", result);\n                    Status = MigrateState.FAIL;\n                    return false;\n                }\n\n                logger?.LogTrace(\"[Completed] SETSLOT {slots} {state} {nodeid}\", ClusterManager.GetRange([.. _sslots]), state, nodeid ?? \"\");\n                return true;\n            }","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/cluster/Server/Migration/MigrationDriver.cs#L16-L52","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar stateBytes = state switch\n{\n    MigrateState.IMPORT => IMPORTING,\n    MigrateState.STABLE => STABLE,\n    MigrateState.NODE => NODE,\n    _ => throw new Exception(\"Invalid SETSLOT Operation\"),\n};\n// after\nDebug.Assert(state is MigrateState.IMPORT or MigrateState.STABLE or MigrateState.NODE);\nvar stateBytes = state switch\n{\n    MigrateState.IMPORT => IMPORTING,\n    MigrateState.STABLE => STABLE,\n    MigrateState.NODE => NODE,\n};","handlingStrategy":"validation","validationCode":"// Validate slot-config state before SETSLOTRANGE\nif (state is not (MigrateState.IMPORT or MigrateState.STABLE or MigrateState.NODE))\n    throw new ArgumentOutOfRangeException(nameof(state), state, \"State must be IMPORT, STABLE, or NODE\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["cluster","migration","setslot","enum-switch","garnet"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}