CloakHQ/CloakBrowser · error · ArgumentException

Cannot choose from an empty string.

Error message

Cannot choose from an empty string.

What it means

ArgumentException thrown by HumanRandom.Choice(string) when the options string is null or empty. The helper mirrors Python's random.choice and requires at least one character to pick from.

Source

Thrown at dotnet/src/CloakBrowser/Human/HumanRandom.cs:52

            (lo, hi) = (hi, lo);
        // Random.Next upper bound is exclusive - add 1 for inclusive range.
        return Rng.Next(lo, hi + 1);
    }

    /// <summary>Random float from a <see cref="Range"/> (min, max), inclusive.</summary>
    public static double RandRange(Range r) => Rand(r.Min, r.Max);

    /// <summary>Random integer from a <see cref="Range"/> (min, max), inclusive.</summary>
    public static int RandIntRange(Range r) => RandInt((int)r.Min, (int)r.Max);

    /// <summary>Return <c>true</c> with the given probability in [0, 1].</summary>
    public static bool Chance(double probability) => Rng.NextDouble() < probability;

    /// <summary>Pick a random character from a non-empty string, like Python's <c>random.choice</c>.</summary>
    public static char Choice(string options)
    {
        if (string.IsNullOrEmpty(options))
            throw new ArgumentException("Cannot choose from an empty string.", nameof(options));
        return options[Rng.Next(options.Length)];
    }

    /// <summary>Pick a random element from a non-empty list, like Python's <c>random.choice</c>.</summary>
    public static T Choice<T>(IReadOnlyList<T> options)
    {
        if (options == null || options.Count == 0)
            throw new ArgumentException("Cannot choose from an empty collection.", nameof(options));
        return options[Rng.Next(options.Count)];
    }

    /// <summary>Block the current thread for <paramref name="ms"/> milliseconds (no-op if &lt;= 0).</summary>
    public static void SleepMs(double ms)
    {
        if (ms > 0)
            Thread.Sleep((int)Math.Round(ms));
    }

View on GitHub (pinned to d6bad5de26)

Solutions

  1. Check string.IsNullOrEmpty before calling Choice
  2. Ensure at least one character class is enabled when building the pool
  3. Default to a fallback charset when the computed pool is empty

Example fix

// before
char c = HumanRandom.Choice(pool);

// after
char c = string.IsNullOrEmpty(pool) ? 'a' : HumanRandom.Choice(pool);
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrEmpty(pool)) pool = "abcdefghijklmnopqrstuvwxyz";

Type guard

static bool IsChoosable(string s) => !string.IsNullOrEmpty(s);

Try / catch

catch (ArgumentException e) when (e.Message.Contains("empty string")) { /* rebuild pool with defaults */ }

Prevention

When it happens

Trigger: Calling HumanRandom.Choice("") or Choice(null) directly, or passing a computed string (e.g. a charset built from config flags) that ends up empty because all options were disabled.

Common situations: Building a character pool from HumanConfig settings where every category (letters, digits, punctuation) is turned off, or filtering a string down to nothing before calling Choice.

Related errors


AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28). Data as JSON: /api/errors/9e51fbb57a9d101f. Report an issue: GitHub.