{"record":{"id":"9e51fbb57a9d101f","repo":"CloakHQ/CloakBrowser","slug":"cannot-choose-from-an-empty-string","errorCode":null,"errorMessage":"Cannot choose from an empty string.","messagePattern":"Cannot choose from an empty string\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/CloakBrowser/Human/HumanRandom.cs","lineNumber":52,"sourceCode":"            (lo, hi) = (hi, lo);\n        // Random.Next upper bound is exclusive - add 1 for inclusive range.\n        return Rng.Next(lo, hi + 1);\n    }\n\n    /// <summary>Random float from a <see cref=\"Range\"/> (min, max), inclusive.</summary>\n    public static double RandRange(Range r) => Rand(r.Min, r.Max);\n\n    /// <summary>Random integer from a <see cref=\"Range\"/> (min, max), inclusive.</summary>\n    public static int RandIntRange(Range r) => RandInt((int)r.Min, (int)r.Max);\n\n    /// <summary>Return <c>true</c> with the given probability in [0, 1].</summary>\n    public static bool Chance(double probability) => Rng.NextDouble() < probability;\n\n    /// <summary>Pick a random character from a non-empty string, like Python's <c>random.choice</c>.</summary>\n    public static char Choice(string options)\n    {\n        if (string.IsNullOrEmpty(options))\n            throw new ArgumentException(\"Cannot choose from an empty string.\", nameof(options));\n        return options[Rng.Next(options.Length)];\n    }\n\n    /// <summary>Pick a random element from a non-empty list, like Python's <c>random.choice</c>.</summary>\n    public static T Choice<T>(IReadOnlyList<T> options)\n    {\n        if (options == null || options.Count == 0)\n            throw new ArgumentException(\"Cannot choose from an empty collection.\", nameof(options));\n        return options[Rng.Next(options.Count)];\n    }\n\n    /// <summary>Block the current thread for <paramref name=\"ms\"/> milliseconds (no-op if &lt;= 0).</summary>\n    public static void SleepMs(double ms)\n    {\n        if (ms > 0)\n            Thread.Sleep((int)Math.Round(ms));\n    }\n","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/dotnet/src/CloakBrowser/Human/HumanRandom.cs#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check string.IsNullOrEmpty before calling Choice","Ensure at least one character class is enabled when building the pool","Default to a fallback charset when the computed pool is empty"],"exampleFix":"// before\nchar c = HumanRandom.Choice(pool);\n\n// after\nchar c = string.IsNullOrEmpty(pool) ? 'a' : HumanRandom.Choice(pool);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrEmpty(pool)) pool = \"abcdefghijklmnopqrstuvwxyz\";","typeGuard":"static bool IsChoosable(string s) => !string.IsNullOrEmpty(s);","tryCatchPattern":"catch (ArgumentException e) when (e.Message.Contains(\"empty string\")) { /* rebuild pool with defaults */ }","preventionTips":["Always default char pools to a non-empty fallback","Validate config-derived pools at startup"],"tags":["humanize","random","argument-validation"],"backgroundTag":"empty-collection-argument","analyzedSha":"d6bad5de261bedf025280ace1d14e800aee13923","analyzedAt":"2026-08-28T14:13:12.918Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}