tui-cs/Terminal.Gui · error · ArgumentOutOfRangeException

Value must be one of the following: {string.Join (", ", Valu

Error message

Value must be one of the following: {string.Join (", ", Values)}

What it means

Thrown by SelectorBase.Value setter when a non-null value is supplied but the Values collection is non-null and does not contain value. The selector's allowed values are explicitly enumerated in Values, so any selection must come from that set. The check runs before the equality short-circuit and before IValue.ValueChanging is raised. (Note the message string is interpolated at runtime, so the exact text includes the joined values.)

Source

Thrown at Terminal.Gui/Views/Selectors/SelectorBase.cs:234

            { Source: { } weakSource } when weakSource.TryGetTarget (out View? src) && src == this => true,
            MouseBinding mouseBinding when mouseBinding.MouseEvent!.Flags.FastHasFlags (MouseFlags.LeftButtonDoubleClicked) => !DoubleClickAccepts,
            KeyBinding { Key: { } } keyBinding when keyBinding.Key == Key.Enter => false,
            null => false,
            _ => true
        };
    }

    /// <summary>
    ///     Gets or sets the value of the selector. Will be <see langword="null"/> if no value is set.
    /// </summary>
    public virtual int? Value
    {
        get;
        set
        {
            if (value is { } && Values is { } && !Values.Contains ((int)value))
            {
                throw new ArgumentOutOfRangeException (nameof (value), @$"Value must be one of the following: {string.Join (", ", Values)}");
            }

            if (field == value)
            {
                return;
            }

            int? previousValue = field;

            // Raise IValue<int?>.ValueChanging (cancellable)
            if (RaiseValueChanging (previousValue, value))
            {
                return;
            }

            Trace.Command (this, "Value", $"{previousValue}->{value}");
            field = value;

View on GitHub (pinned to 2e47b11478)

Solutions

  1. Verify membership before assigning: if (selector.Values is null || selector.Values.Contains(v)) selector.Value = v;
  2. After changing Values, clear or re-clamp Value to a member of the new set.
  3. For enums, prefer OptionSelectorTEnum which derives Values from the enum so membership is guaranteed.

Example fix

// before
selector.Value = candidate; // candidate not in Values -> throws 172

// after
if (selector.Values is null || selector.Values.Contains(candidate))
{
    selector.Value = candidate;
}
Defensive patterns

Strategy: validation

Validate before calling

if (selector.Values is null || selector.Values.Contains(candidate))
{
    selector.Value = candidate;
}

Type guard

static bool ValueIsAllowed(SelectorBase s, int v) => s.Values is null || s.Values.Contains(v);

Prevention

When it happens

Trigger: Setting Value to an int not present in Values; assigning a value captured before Values was populated or after Values changed; enum-to-int conversion that yields a value outside the configured set; stale binding pushing an old selection.

Common situations: Rebinding the selector with a smaller Values set while a previous Value persists; converting an enum to int where the int isn't in the list; default(int)=0 assigned when 0 is not among Values.

Related errors


AI-assisted analysis of tui-cs/Terminal.Gui@2e47b11478 (2026-08-13). Data as JSON: /api/errors/195ef76332beee38. Report an issue: GitHub.