{"record":{"id":"723a069f961613dc","repo":"Devolutions/UniGetUI","slug":"running-or-queued-operations-cannot-be-forgotten","errorCode":null,"errorMessage":"Running or queued operations cannot be forgotten.","messagePattern":"Running or queued operations cannot be forgotten\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":400,"severity":"warning","filePath":"src/UniGetUI.Interface.IpcApi/IpcOperationApi.cs","lineNumber":266,"sourceCode":"            case \"run-next\":\n                tracked.Operation.RunNext();\n                break;\n            case \"run-last\":\n                tracked.Operation.BackOfTheQueue();\n                break;\n            default:\n                throw new InvalidOperationException($\"Unsupported queue action \\\"{action}\\\".\");\n        }\n\n        return IpcCommandResult.Success(\"reorder-operation\");\n    }\n\n    public static IpcCommandResult ForgetOperation(string operationId)\n    {\n        var tracked = GetTrackedOperation(operationId);\n        if (IsActive(tracked.Operation.Status))\n        {\n            throw new InvalidOperationException(\n                \"Running or queued operations cannot be forgotten.\"\n            );\n        }\n\n        ForgetTracking(operationId);\n        return IpcCommandResult.Success(\"forget-operation\");\n    }\n\n    public static void ForgetTracking(string operationId)\n    {\n        Operations.TryRemove(operationId, out _);\n    }\n\n    private static TrackedOperation GetTrackedOperation(string operationId)\n    {\n        ArgumentException.ThrowIfNullOrWhiteSpace(operationId);\n\n        return Operations.TryGetValue(operationId.Trim(), out var tracked)","sourceCodeStart":248,"sourceCodeEnd":284,"githubUrl":"https://github.com/Devolutions/UniGetUI/blob/9b1d7d0eab91620fc15c86b36676532095936ae3/src/UniGetUI.Interface.IpcApi/IpcOperationApi.cs#L248-L284","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check CanForget (or AvailableRetryModes being non-empty implies terminal) before calling ForgetOperation.","If the operation is active, call CancelOperation first, wait for status to change, then ForgetOperation.","Use the pruning mechanism (MaxTrackedOperations = 200) for automatic cleanup of old completed operations instead of manual forgetting."],"exampleFix":"// before — forget without checking state\nIpcOperationApi.ForgetOperation(opId);\n// after\nvar info = IpcOperationApi.GetOperation(opId);\nif (info.CanForget)\n    IpcOperationApi.ForgetOperation(opId);\nelse\n    IpcOperationApi.CancelOperation(opId); // cancel first, forget later","handlingStrategy":"validation","validationCode":"var info = IpcOperationApi.GetOperation(operationId);\nif (!info.CanForget)\n    throw new InvalidOperationException($\"Operation {operationId} is still active. Cancel it first.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Gate forget UI on the CanForget field from IpcOperationInfo.","Cancel active operations first, wait for terminal status, then forget.","Rely on the automatic pruning (MaxTrackedOperations=200) for routine cleanup."],"tags":["operations","ipc","validation","state-machine","tracking"],"backgroundTag":null,"analyzedSha":"9b1d7d0eab91620fc15c86b36676532095936ae3","analyzedAt":"2026-08-13T12:19:18.278Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}