Devolutions/UniGetUI · error · InvalidOperationException

Unsupported retry mode

Error message

Unsupported retry mode "{retryMode}".

What it means

NormalizeRetryMode throws when the retryMode string (matched case-insensitively, trimmed) is not one of: retry, retry-as-admin, retry-interactive, retry-no-hash-check. A null/empty mode is permitted and defaults to plain Retry; any other spelling is rejected.

Solutions

  1. Restrict retryMode to the four literal tokens
  2. Drive the value from the AvailableRetryModes list returned on IpcOperationInfo rather than hardcoding
  3. Whitelist-validate client-side before the call

Example fix

// before
IpcOperationApi.RetryOperation(opId, mode: "admin");
// after
var allowed = info.AvailableRetryModes; // ["retry","retry-as-admin",...]
var mode = allowed.Contains(userChoice, StringComparer.OrdinalIgnoreCase) ? userChoice : "retry";
IpcOperationApi.RetryOperation(opId, mode: mode);
Defensive patterns

Strategy: validation

Validate before calling

static readonly HashSet<string> RetryModes = new(StringComparer.OrdinalIgnoreCase)
    { "retry", "retry-as-admin", "retry-interactive", "retry-no-hash-check" };

if (!RetryModes.Contains(retryMode))
    throw new ArgumentException($"Bad retry mode: {retryMode}");

Prevention

When it happens

Trigger: Calling RetryOperation with a value like "admin", "retry-admin", "force", or "as-admin".

Common situations: Client built the mode from free-form user input; shorthand used in UI leaked into the API; cross-version rename of a token.

Related errors


AI-assisted analysis of Devolutions/UniGetUI@9b1d7d0eab (2026-08-13). Data as JSON: /api/errors/a5c084ec13434cda. Report an issue: GitHub.

Appendix: source

Thrown at src/UniGetUI.Interface.IpcApi/IpcOperationApi.cs:436

        }

        return retryModes;
    }

    private static string NormalizeRetryMode(string? retryMode)
    {
        if (string.IsNullOrWhiteSpace(retryMode))
        {
            return AbstractOperation.RetryMode.Retry;
        }

        return retryMode.Trim().ToLowerInvariant() switch
        {
            "retry" => AbstractOperation.RetryMode.Retry,
            "retry-as-admin" => AbstractOperation.RetryMode.Retry_AsAdmin,
            "retry-interactive" => AbstractOperation.RetryMode.Retry_Interactive,
            "retry-no-hash-check" => AbstractOperation.RetryMode.Retry_SkipIntegrity,
            _ => throw new InvalidOperationException(
                $"Unsupported retry mode \"{retryMode}\"."
            ),
        };
    }

    private static string ToRetryModeName(string retryMode)
    {
        return retryMode switch
        {
            var mode when mode == AbstractOperation.RetryMode.Retry => "retry",
            var mode when mode == AbstractOperation.RetryMode.Retry_AsAdmin => "retry-as-admin",
            var mode when mode == AbstractOperation.RetryMode.Retry_Interactive
                => "retry-interactive",
            var mode when mode == AbstractOperation.RetryMode.Retry_SkipIntegrity
                => "retry-no-hash-check",
            _ => retryMode,
        };
    }

View on GitHub (pinned to 9b1d7d0eab)