dotnet/orleans · error · ArgumentNullException
Value cannot be null. (Parameter 'collection')
Error message
Value cannot be null. (Parameter 'collection')
What it means
Thrown by AzureTableDataManager.DeleteTableEntriesAsync when the collection argument is null. The method performs a batch (transaction) delete of pre-existing entities by eTag, so a null list is rejected before any batch is built.
Source
Thrown at src/Azure/Shared/Storage/AzureTableDataManager.cs:469
public Task<List<(T Entity, string ETag)>> ReadAllTableEntriesAsync(
CancellationToken cancellationToken = default)
{
return ReadTableEntriesAndEtagsAsync(null, cancellationToken);
}
/// <summary>
/// Deletes a set of already existing data entries in the table, by using eTag.
/// Fails if the data does not already exist or if eTag does not match.
/// </summary>
/// <param name="collection">Data entries and their corresponding etags to be deleted from the table.</param>
/// <returns>Completion promise for this storage operation.</returns>
public async Task DeleteTableEntriesAsync(List<(T Entity, string ETag)> collection)
{
const string operation = "DeleteTableEntries";
var startTime = DateTime.UtcNow;
LogTraceTableEntries(Logger, operation, new(collection), TableName);
if (collection == null) throw new ArgumentNullException(nameof(collection));
if (collection.Count > this.StoragePolicyOptions.MaxBulkUpdateRows)
{
throw new ArgumentOutOfRangeException(nameof(collection), collection.Count,
"Too many rows for bulk delete - max " + this.StoragePolicyOptions.MaxBulkUpdateRows);
}
if (collection.Count == 0)
{
return;
}
try
{
var entityBatch = new List<TableTransactionAction>();
foreach (var tuple in collection)
{
T item = tuple.Entity;View on GitHub (pinned to fca799fa70)
Solutions
- Pass a non-null List<(T Entity, string ETag)> (use an empty list when there is nothing to delete — the method returns early for count 0).
- Coalesce nulls to empty lists at the call site.
- Use '?? new()' or '?? Enumerable.Empty' patterns when sourcing the list.
Example fix
// before await manager.DeleteTableEntriesAsync(maybeEntries); // maybeEntries null // after await manager.DeleteTableEntriesAsync(maybeEntries ?? new List<(MyEntity Entity, string ETag)>());
Defensive patterns
Strategy: validation
Validate before calling
var entries = collection ?? new List<(T Entity, string ETag)>(); await manager.DeleteTableEntriesAsync(entries);
Type guard
static bool HasCollection<T>(List<(T Entity, string ETag)>? c) => c is not null;
Try / catch
catch (ArgumentNullException ex) when (ex.ParamName == "collection") { /* coalesce null to an empty list */ } Prevention
- Default to empty lists rather than null when aggregating deletables.
- Use '?? new()' at the call site.
When it happens
Trigger: Calling DeleteTableEntriesAsync(null) — e.g. a cleanup routine that returned null instead of an empty list, or a deserialization that produced null.
Common situations: Code that builds a list conditionally and forgets the empty-default; aggregating deletables where no candidates exist; refactor that changed the list source.
Related errors
- Too many rows for bulk delete - max {this.StoragePolicyOptio
- Value cannot be null. (Parameter 'createClientCallback')
- Value cannot be null. (Parameter 'connectionString')
- Value cannot be null. (Parameter 'serviceUri')
- Value cannot be null. (Parameter 'tokenCredential')
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/f6326e434cb88886.
Report an issue: GitHub.