{"record":{"id":"cc2f5f056f0a1bf8","repo":"CloakHQ/CloakBrowser","slug":"cannot-choose-from-an-empty-collection","errorCode":null,"errorMessage":"Cannot choose from an empty collection.","messagePattern":"Cannot choose from an empty collection\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/CloakBrowser/Human/HumanRandom.cs","lineNumber":60,"sourceCode":"    /// <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\n    /// <summary>Asynchronously wait for <paramref name=\"ms\"/> milliseconds (no-op if &lt;= 0).</summary>\n    public static Task SleepMsAsync(double ms)\n    {\n        if (ms <= 0)\n            return Task.CompletedTask;\n        return Task.Delay((int)Math.Round(ms));\n    }\n}","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/CloakHQ/CloakBrowser/blob/d6bad5de261bedf025280ace1d14e800aee13923/dotnet/src/CloakBrowser/Human/HumanRandom.cs#L42-L78","documentation":"ArgumentException thrown by the generic HumanRandom.Choice<T> when the list is null or has zero elements. A random index cannot be produced from an empty collection.","triggerScenarios":"Calling HumanRandom.Choice(list) with an empty or null IReadOnlyList, e.g. a filtered list of candidates (links, viewport waypoints, dictionary keys) that matched nothing.","commonSituations":"Filtering collections by predicate before random selection (no matches), empty config lists, or empty dictionaries passed as option pools.","solutions":["Guard with a Count > 0 check (or ?.Count check) before calling Choice","Fix the filter/predicate so it can produce at least one candidate","Provide a sensible default/fallback element when the list is empty"],"exampleFix":"// before\nvar pick = HumanRandom.Choise(candidates);\n\n// after\nvar pick = candidates is { Count: > 0 } ? HumanRandom.Choice(candidates) : fallback;","handlingStrategy":"validation","validationCode":"if (candidates is not { Count: > 0 }) candidates = new List<T> { fallback };","typeGuard":"static bool IsChoosable<T>(IReadOnlyList<T> l) => l is { Count: > 0 };","tryCatchPattern":"catch (ArgumentException e) when (e.Message.Contains(\"empty collection\")) { /* widen filter and retry */ }","preventionTips":["Check Count before Choice","Ensure predicates can match at least one element","Unit-test filters against realistic data"],"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"}