{"record":{"id":"bda0de6c5b128452","repo":"microsoft/garnet","slug":"invalid-failover-status","errorCode":null,"errorMessage":"invalid failover status","messagePattern":"invalid failover status","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"libs/cluster/Server/Failover/FailoverStatus.cs","lineNumber":43,"sourceCode":"        /// <summary>\n        /// Convert failover to string message for info command.\n        /// </summary>\n        /// <param name=\"status\">Failover status type.</param>\n        /// <returns>String message for provided status, otherwise exception is thrown.</returns>\n        /// <exception cref=\"Exception\"></exception>\n        public static string GetFailoverStatus(FailoverStatus? status)\n        {\n            return status switch\n            {\n                FailoverStatus.NO_FAILOVER => \"no-failover\",\n                FailoverStatus.BEGIN_FAILOVER => \"begin-failover\",\n                FailoverStatus.ISSUING_PAUSE_WRITES => \"issuing-pause-writes\",\n                FailoverStatus.WAITING_FOR_SYNC => \"waiting-for-sync\",\n                FailoverStatus.FAILOVER_IN_PROGRESS => \"failover-in-progress\",\n                FailoverStatus.TAKING_OVER_AS_PRIMARY => \"taking-over-as-primary\",\n                FailoverStatus.FAILOVER_COMPLETED => \"failover-completed\",\n                FailoverStatus.FAILOVER_ABORTED => \"failover-aborted\",\n                _ => throw new Exception(\"invalid failover status\"),\n            };\n        }\n    }\n}","sourceCodeStart":25,"sourceCodeEnd":47,"githubUrl":"https://github.com/microsoft/garnet/blob/951b0fc6838721f89d102c2bbe1b914e8d39d700/libs/cluster/Server/Failover/FailoverStatus.cs#L25-L47","documentation":"Thrown by FailoverUtils.GetFailoverStatus when the supplied FailoverStatus? cannot be mapped to an info-command string. The switch enumerates all eight defined FailoverStatus members, so the default arm only fires for a null status or a value cast outside the enum range. It surfaces during CLUSTER failover when reporting state via the INFO command.","triggerScenarios":"Calling GetFailoverStatus(null), or casting an arbitrary byte to (FailoverStatus) outside 0..7 (e.g. an unsafe cast or uninitialized field read before the failover state machine sets a value).","commonSituations":"A failover status field read before initialization (still null), a concurrent reset that nulls the status mid-read, or a future enum member added without updating this switch.","solutions":["Ensure the failover state machine initializes the status field to NO_FAILOVER before any INFO/GetFailoverStatus read path can observe it.","If the caller can legitimately observe null, handle it before calling (e.g. treat null as NO_FAILOVER) instead of relying on the switch default.","When extending FailoverStatus, add the new arm to the switch to keep it exhaustive."],"exampleFix":"// before\nreturn FailoverUtils.GetFailoverStatus(currentStatus);\n// after\nvar status = currentStatus ?? FailoverStatus.NO_FAILOVER;\nreturn FailoverUtils.GetFailoverStatus(status);","handlingStrategy":"validation","validationCode":"// Validate before calling GetFailoverStatus\nvar status = currentStatus ?? FailoverStatus.NO_FAILOVER;\nif ((byte)status > (byte)FailoverStatus.FAILOVER_ABORTED)\n    throw new ArgumentOutOfRangeException(nameof(status), status, \"Unknown FailoverStatus\");\nvar msg = FailoverUtils.GetFailoverStatus(status);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Initialize the failover status field to NO_FAILOVER at construction so reads never see null.","Treat null defensively as NO_FAILOVER before invoking GetFailoverStatus.","Add a unit test that the switch covers every FailoverStatus member."],"tags":["cluster","failover","enum-switch","garnet"],"backgroundTag":null,"analyzedSha":"951b0fc6838721f89d102c2bbe1b914e8d39d700","analyzedAt":"2026-08-13T19:01:32.939Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}