microsoft/garnet · error · Exception

invalid failover status

Error message

invalid failover status

What it means

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.

Solutions

  1. Ensure the failover state machine initializes the status field to NO_FAILOVER before any INFO/GetFailoverStatus read path can observe it.
  2. 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.
  3. When extending FailoverStatus, add the new arm to the switch to keep it exhaustive.

Example fix

// before
return FailoverUtils.GetFailoverStatus(currentStatus);
// after
var status = currentStatus ?? FailoverStatus.NO_FAILOVER;
return FailoverUtils.GetFailoverStatus(status);
Defensive patterns

Strategy: validation

Validate before calling

// Validate before calling GetFailoverStatus
var status = currentStatus ?? FailoverStatus.NO_FAILOVER;
if ((byte)status > (byte)FailoverStatus.FAILOVER_ABORTED)
    throw new ArgumentOutOfRangeException(nameof(status), status, "Unknown FailoverStatus");
var msg = FailoverUtils.GetFailoverStatus(status);

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/bda0de6c5b128452. Report an issue: GitHub.

Appendix: source

Thrown at libs/cluster/Server/Failover/FailoverStatus.cs:43

        /// <summary>
        /// Convert failover to string message for info command.
        /// </summary>
        /// <param name="status">Failover status type.</param>
        /// <returns>String message for provided status, otherwise exception is thrown.</returns>
        /// <exception cref="Exception"></exception>
        public static string GetFailoverStatus(FailoverStatus? status)
        {
            return status switch
            {
                FailoverStatus.NO_FAILOVER => "no-failover",
                FailoverStatus.BEGIN_FAILOVER => "begin-failover",
                FailoverStatus.ISSUING_PAUSE_WRITES => "issuing-pause-writes",
                FailoverStatus.WAITING_FOR_SYNC => "waiting-for-sync",
                FailoverStatus.FAILOVER_IN_PROGRESS => "failover-in-progress",
                FailoverStatus.TAKING_OVER_AS_PRIMARY => "taking-over-as-primary",
                FailoverStatus.FAILOVER_COMPLETED => "failover-completed",
                FailoverStatus.FAILOVER_ABORTED => "failover-aborted",
                _ => throw new Exception("invalid failover status"),
            };
        }
    }
}

View on GitHub (pinned to 951b0fc683)