Devolutions/UniGetUI · warning · InvalidOperationException
tailLines must be greater than or equal to zero.
Error message
tailLines must be greater than or equal to zero.
What it means
Thrown by GetOperationOutput when the optional tailLines parameter is provided but is negative (less than zero). tailLines controls how many trailing output lines to return; zero means return all lines (the snapshot method treats <=0 as 'all'), while negative is rejected as invalid input.
Source
Thrown at src/UniGetUI.Interface.IpcApi/IpcOperationApi.cs:184
CanCancel = info.CanCancel,
CanForget = info.CanForget,
AvailableQueueActions = info.AvailableQueueActions,
AvailableRetryModes = info.AvailableRetryModes,
Package = info.Package,
ManagerName = info.ManagerName,
SourceName = info.SourceName,
Output = tracked.GetOutputSnapshot(),
};
}
public static IpcOperationOutputResult GetOperationOutput(
string operationId,
int? tailLines = null
)
{
if (tailLines.HasValue && tailLines.Value < 0)
{
throw new InvalidOperationException("tailLines must be greater than or equal to zero.");
}
var tracked = GetTrackedOperation(operationId);
return new IpcOperationOutputResult
{
OperationId = tracked.Operation.Metadata.Identifier,
LineCount = tracked.GetOutputCount(),
Output = tracked.GetOutputSnapshot(tailLines),
};
}
public static IpcCommandResult CancelOperation(string operationId)
{
var tracked = GetTrackedOperation(operationId);
if (!IsActive(tracked.Operation.Status))
{
throw new InvalidOperationException(
"Only queued or running operations can be canceled."View on GitHub (pinned to 9b1d7d0eab)
Solutions
- Pass null or omit tailLines entirely to get all output lines.
- Pass 0 or a positive integer to limit the tail.
- Ensure any computed tailLines value is clamped to >= 0 before calling.
Example fix
// before var result = IpcOperationApi.GetOperationOutput(opId, tailLines: lineCount - 10); // after — guard against negative var tail = Math.Max(0, lineCount - 10); var result = IpcOperationApi.GetOperationOutput(opId, tailLines: tail == 0 ? null : tail);
Defensive patterns
Strategy: validation
Validate before calling
if (tailLines.HasValue && tailLines.Value < 0)
throw new ArgumentOutOfRangeException(nameof(tailLines), "Must be >= 0.");
// Clamp or convert to null for 'all lines'
tailLines = tailLines.HasValue && tailLines.Value <= 0 ? null : tailLines; Prevention
- Use null or omit tailLines for all output lines.
- Use 0 or positive for tail-only output.
- Clamp computed values to >= 0 before passing.
When it happens
Trigger: Calling GetOperationOutput(operationId, tailLines) where tailLines is a negative integer. The parameter is nullable int, so null (omit) is valid and means 'all lines'. A value of 0 is valid and also returns all lines per the GetOutputSnapshot logic.
Common situations: IPC client passes -1 as a 'give me everything' sentinel (should use null or 0 instead). Arithmetic on line counts produces a negative value when the operation has no output yet. Misunderstanding the parameter semantics.
Related errors
- Unsupported queue action "{action}".
- Only queued or running operations can be canceled.
- Running or queued operations cannot be retried.
- Retry mode "{retryMode}" is not supported for operation {ope
- Only queued operations can be reordered.
AI-assisted analysis of Devolutions/UniGetUI@9b1d7d0eab (2026-08-13).
Data as JSON: /api/errors/4b6e6efd15842934.
Report an issue: GitHub.