{"record":{"id":"5bba73fd05a4fbe8","repo":"Devolutions/UniGetUI","slug":"only-queued-or-running-operations-can-be-canceled","errorCode":null,"errorMessage":"Only queued or running operations can be canceled.","messagePattern":"Only queued or running operations can be canceled\\.","errorType":"validation","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"src/UniGetUI.Interface.IpcApi/IpcOperationApi.cs","lineNumber":201,"sourceCode":"        {\n            throw new InvalidOperationException(\"tailLines must be greater than or equal to zero.\");\n        }\n\n        var tracked = GetTrackedOperation(operationId);\n        return new IpcOperationOutputResult\n        {\n            OperationId = tracked.Operation.Metadata.Identifier,\n            LineCount = tracked.GetOutputCount(),\n            Output = tracked.GetOutputSnapshot(tailLines),\n        };\n    }\n\n    public static IpcCommandResult CancelOperation(string operationId)\n    {\n        var tracked = GetTrackedOperation(operationId);\n        if (!IsActive(tracked.Operation.Status))\n        {\n            throw new InvalidOperationException(\n                \"Only queued or running operations can be canceled.\"\n            );\n        }\n\n        tracked.Operation.Cancel();\n        return IpcCommandResult.Success(\"cancel-operation\");\n    }\n\n    public static IpcCommandResult RetryOperation(string operationId, string? retryMode)\n    {\n        var tracked = GetTrackedOperation(operationId);\n        if (IsActive(tracked.Operation.Status))\n        {\n            throw new InvalidOperationException(\n                \"Running or queued operations cannot be retried.\"\n            );\n        }\n","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/Devolutions/UniGetUI/blob/9b1d7d0eab91620fc15c86b36676532095936ae3/src/UniGetUI.Interface.IpcApi/IpcOperationApi.cs#L183-L219","documentation":"Thrown by CancelOperation when the operation's status is not InQueue or Running (i.e., IsActive returns false). Only operations that are actively queued or executing can be canceled. Completed, failed, canceled, or forgotten operations cannot be canceled again.","triggerScenarios":"Calling CancelOperation with an operationId for an operation whose status is not InQueue or Running. The operation must first be found by GetTrackedOperation (which throws a different error if not tracked), then its status is checked.","commonSituations":"Race condition: the operation finished between the client's last status check and the cancel call. Client UI shows a stale status and the cancel button is enabled for an already-completed operation. Double-clicking cancel after the first click already succeeded.","solutions":["Check the operation status via GetOperation or ListOperations before calling CancelOperation.","Use the CanCancel flag from IpcOperationInfo as the client-side gate for the cancel button.","Handle this exception gracefully in the UI — the operation already completed, so refresh its state."],"exampleFix":"// before — cancel without status check\nIpcOperationApi.CancelOperation(opId);\n// after\nvar info = IpcOperationApi.GetOperation(opId);\nif (info.CanCancel)\n    IpcOperationApi.CancelOperation(opId);","handlingStrategy":"validation","validationCode":"var info = IpcOperationApi.GetOperation(operationId);\nif (!info.CanCancel)\n    throw new InvalidOperationException($\"Operation {operationId} cannot be canceled (status: {info.Status}).\");","typeGuard":null,"tryCatchPattern":"try\n{\n    IpcOperationApi.CancelOperation(operationId);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"cannot be canceled\"))\n{\n    // Operation already completed — refresh UI state\n    logger.LogDebug(\"Operation {Id} already completed\", operationId);\n}","preventionTips":["Gate cancel UI on the CanCancel field from IpcOperationInfo.","Poll operation status periodically to keep UI state fresh.","Handle the 'already completed' case gracefully rather than surfacing an error."],"tags":["operations","ipc","validation","state-machine"],"backgroundTag":null,"analyzedSha":"9b1d7d0eab91620fc15c86b36676532095936ae3","analyzedAt":"2026-08-13T12:19:18.278Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}