Devolutions/UniGetUI · warning · InvalidOperationException

Running or queued operations cannot be forgotten.

Error message

Running or queued operations cannot be forgotten.

What it means

Thrown by ForgetOperation when the operation's status is InQueue or Running (IsActive returns true). Forgetting removes an operation from the tracking dictionary, which is only safe for terminal operations. Active operations must be canceled first and allowed to reach a terminal state before they can be forgotten.

Source

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

            case "run-next":
                tracked.Operation.RunNext();
                break;
            case "run-last":
                tracked.Operation.BackOfTheQueue();
                break;
            default:
                throw new InvalidOperationException($"Unsupported queue action \"{action}\".");
        }

        return IpcCommandResult.Success("reorder-operation");
    }

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

        ForgetTracking(operationId);
        return IpcCommandResult.Success("forget-operation");
    }

    public static void ForgetTracking(string operationId)
    {
        Operations.TryRemove(operationId, out _);
    }

    private static TrackedOperation GetTrackedOperation(string operationId)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(operationId);

        return Operations.TryGetValue(operationId.Trim(), out var tracked)

View on GitHub (pinned to 9b1d7d0eab)

Solutions

  1. Check CanForget (or AvailableRetryModes being non-empty implies terminal) before calling ForgetOperation.
  2. If the operation is active, call CancelOperation first, wait for status to change, then ForgetOperation.
  3. Use the pruning mechanism (MaxTrackedOperations = 200) for automatic cleanup of old completed operations instead of manual forgetting.

Example fix

// before — forget without checking state
IpcOperationApi.ForgetOperation(opId);
// after
var info = IpcOperationApi.GetOperation(opId);
if (info.CanForget)
    IpcOperationApi.ForgetOperation(opId);
else
    IpcOperationApi.CancelOperation(opId); // cancel first, forget later
Defensive patterns

Strategy: validation

Validate before calling

var info = IpcOperationApi.GetOperation(operationId);
if (!info.CanForget)
    throw new InvalidOperationException($"Operation {operationId} is still active. Cancel it first.");

Prevention

When it happens

Trigger: Calling ForgetOperation for an operation that is still queued or running. The operation is found via GetTrackedOperation but its status indicates it is active. CanForget on IpcOperationInfo is false for active operations.

Common situations: Client attempts to clean up the operations list while operations are still in progress. Race condition: operation finishes between status check and forget call. Forgetting an operation that is InQueue but hasn't started executing yet.

Related errors


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