stride3d/stride · error · ArgumentException
Invalid 'source' IEnumerable.
Error message
Invalid 'source' IEnumerable.
What it means
EnumerableExtensions.IsNullOrEmpty checks whether an IEnumerable is null or has no elements by obtaining its enumerator. If source.GetEnumerator() returns null (legal for a null-returning custom implementation), it throws ArgumentException with the message "Invalid 'source' IEnumerable.". This is a defensive check for broken IEnumerable implementations, not for a null source (which is handled by returning true).
Solutions
- Fix the IEnumerable implementation so GetEnumerator() returns a valid non-null IEnumerator (or throw, or return an empty enumerator)
- Do not mock with null enumerators; have test stubs return IEnumerator.Empty-style empty enumerators
- If you must test suspicious sources, wrap the call in try/catch for ArgumentException
- Prefer checking source == null and using Any()/Count with a working collection before relying on IsNullOrEmpty
Example fix
// before public IEnumerator GetEnumerator() => null; // broken stub // after public IEnumerator GetEnumerator() => Array.Empty<object>().GetEnumerator();
Defensive patterns
Strategy: type-guard
Validate before calling
if (source == null) return true;
if (source.GetEnumerator() is null)
throw new ArgumentException("Source must return a valid enumerator."); Type guard
static bool IsValidEnumerable(IEnumerable? source) =>
source == null || source.GetEnumerator() != null; Try / catch
try
{
bool empty = enumerable.IsNullOrEmpty();
}
catch (ArgumentException ex) when (ex.Message == "Invalid 'source' IEnumerable.")
{
// source is a broken IEnumerable: fix or replace the implementation
} Prevention
- Never return null from GetEnumerator in custom collections; return an empty enumerator instead
- Check that test mocks of IEnumerable return a real enumerator
- Prefer Any() on verified non-null collections when implementations are trusted
When it happens
Trigger: Passing an IEnumerable whose GetEnumerator() method returns null — e.g. a mis-implemented custom collection, a stub/mock returning null, or an exotic enumerable wrapper that yields no enumerator.
Common situations: Mocking IEnumerable in unit tests with a stub whose GetEnumerator returns null; custom lazy/streaming collections that fail to produce an enumerator; calling IsNullOrEmpty on a structurally broken third-party collection.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- A file path cannot end with with directory char '\' or '/'…
- A Gear constraint requires two rigidbodies.
- A MaterialPass can only belong to a single Material
- A routed event named
- Already scheduled, call Unschedule before running this…
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/8648cae7f53a0729.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core/Extensions/EnumerableExtensions.cs:22
using System.Collections;
using System.Diagnostics.Contracts;
namespace Stride.Core.Extensions;
public static class EnumerableExtensions
{
/// <summary>
/// Tells whether a sequence is null or empty.
/// </summary>
/// <param name="source">The source sequence.</param>
/// <returns>Returns true if the sequence is null or empty, false if it is not null and contains at least one element.</returns>
[Pure]
public static bool IsNullOrEmpty(this IEnumerable? source)
{
if (source == null)
return true;
var enumerator = source.GetEnumerator() ?? throw new ArgumentException("Invalid 'source' IEnumerable.");
return enumerator.MoveNext() == false;
}
/// <summary>
/// Executes an action for each (casted) item of the given enumerable.
/// </summary>
/// <typeparam name="T">Type of the item value in the enumerable.</typeparam>
/// <param name="source">Input enumerable to work on.</param>
/// <param name="action">Action performed for each item in the enumerable.</param>
/// <remarks>This extension method do not yield. It acts just like a foreach statement, and performs a cast to a typed enumerable in the middle.</remarks>
public static void ForEach<T>(this IEnumerable source, Action<T> action)
{
source.Cast<T>().ForEach(action);
}
/// <summary>
/// Executes an action for each item of the given enumerable.
/// </summary>View on GitHub (pinned to 96fad776d2)