Devolutions/UniGetUI · warning · InvalidOperationException

Running or queued operations cannot be retried.

Error message

Running or queued operations cannot be retried.

What it means

Thrown by RetryOperation when the operation's status is InQueue or Running (IsActive returns true). Retrying an operation that is still active would create a duplicate or conflict. The operation must have reached a terminal state (succeeded, failed, or canceled) before retry is allowed.

Source

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

    {
        var tracked = GetTrackedOperation(operationId);
        if (!IsActive(tracked.Operation.Status))
        {
            throw new InvalidOperationException(
                "Only queued or running operations can be canceled."
            );
        }

        tracked.Operation.Cancel();
        return IpcCommandResult.Success("cancel-operation");
    }

    public static IpcCommandResult RetryOperation(string operationId, string? retryMode)
    {
        var tracked = GetTrackedOperation(operationId);
        if (IsActive(tracked.Operation.Status))
        {
            throw new InvalidOperationException(
                "Running or queued operations cannot be retried."
            );
        }

        string normalizedRetryMode = NormalizeRetryMode(retryMode);
        var availableRetryModes = GetRetryModes(tracked.Operation);
        if (!availableRetryModes.Contains(ToRetryModeName(normalizedRetryMode)))
        {
            throw new InvalidOperationException(
                $"Retry mode \"{retryMode}\" is not supported for operation {operationId}."
            );
        }

        tracked.Operation.Retry(normalizedRetryMode);
        return IpcCommandResult.Success("retry-operation");
    }

    public static IpcCommandResult ReorderOperation(string operationId, string action)

View on GitHub (pinned to 9b1d7d0eab)

Solutions

  1. Wait for the operation to reach a terminal state (check via GetOperation or ListOperations polling).
  2. Use the AvailableRetryModes field from IpcOperationInfo — it is empty for active operations, serving as a client-side indicator.
  3. If the operation is truly stuck, call CancelOperation first, wait for it to register as canceled, then RetryOperation.

Example fix

// before
IpcOperationApi.RetryOperation(opId, "retry");
// after
var info = IpcOperationApi.GetOperation(opId);
if (info.AvailableRetryModes.Count > 0)
    IpcOperationApi.RetryOperation(opId, info.AvailableRetryModes[0]);
Defensive patterns

Strategy: validation

Validate before calling

var info = IpcOperationApi.GetOperation(operationId);
if (info.AvailableRetryModes.Count == 0)
    throw new InvalidOperationException($"Operation {operationId} is still active and cannot be retried.");

Try / catch

try
{
    IpcOperationApi.RetryOperation(operationId, retryMode);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("cannot be retried"))
{
    // Still active — wait for terminal state
    logger.LogWarning("Cannot retry {Id} yet: still active", operationId);
}

Prevention

When it happens

Trigger: Calling RetryOperation for an operation that is still queued or running. The operation is found and active, so this guard fires before the retry-mode validation.

Common situations: Client retries an operation that appears stuck but is still technically Running. Race condition: the user clicks retry while the operation is mid-execution. UI shows a retry button for a running operation due to stale data.

Related errors


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