dotnet/orleans · error · ArgumentOutOfRangeException

MaxMetadataOnlyConflictRetries must be non-negative.

Error message

MaxMetadataOnlyConflictRetries must be non-negative.

What it means

AzureTableJournalStorageOptions.MaxMetadataOnlyConflictRetries was set to a negative value. The constructor (AzureTableJournalStorage.cs:1278) requires it non-negative because it counts retry attempts after a metadata-only ETag conflict (zero means no in-place retry, falling back immediately to InconsistentStateException). The argument blamed is `options`.

Source

Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorage.cs:1280

            ArgumentNullException.ThrowIfNull(tableClientProvider);

            Logger = logger;
            Options = options.Value;
            ArgumentNullException.ThrowIfNull(Options);
            AzureTableJournalStorageOptions.ValidateTableName(Options.TableName);
            if (Options.CompactionRowCountThreshold <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureTableJournalStorageOptions.CompactionRowCountThreshold)} must be positive.");
            }

            if (Options.CompactionSizeThreshold <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureTableJournalStorageOptions.CompactionSizeThreshold)} must be positive.");
            }

            if (Options.MaxMetadataOnlyConflictRetries < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureTableJournalStorageOptions.MaxMetadataOnlyConflictRetries)} must be non-negative.");
            }

            if (Options.MetadataOnlyConflictInitialBackoff < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureTableJournalStorageOptions.MetadataOnlyConflictInitialBackoff)} must be non-negative.");
            }

            if (Options.MetadataOnlyConflictMaxBackoff < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureTableJournalStorageOptions.MetadataOnlyConflictMaxBackoff)} must be non-negative.");
            }

            JournalFormatKey = journalFormatKey;
            TableClientProvider = tableClientProvider;
            Instruments = instruments;
        }

        public ILogger<AzureTableJournalStorage> Logger { get; }

View on GitHub (pinned to fca799fa70)

Solutions

  1. Set MaxMetadataOnlyConflictRetries to a non-negative integer (default 5).
  2. Use 0 to disable in-place metadata-conflict retries if immediate fallback is desired.
  3. Validate via IValidateOptions<T> at startup.

Example fix

// before
options.MaxMetadataOnlyConflictRetries = -1;

// after
options.MaxMetadataOnlyConflictRetries = AzureTableJournalStorageOptions.DEFAULT_MAX_METADATA_ONLY_CONFLICT_RETRIES;
Defensive patterns

Strategy: validation

Validate before calling

if (options.MaxMetadataOnlyConflictRetries < 0)
    throw new ArgumentOutOfRangeException(nameof(options.MaxMetadataOnlyConflictRetries), "Must be non-negative");

Type guard

static bool IsValidMaxRetries(int v) => v >= 0;

Prevention

When it happens

Trigger: Configuring MaxMetadataOnlyConflictRetries < 0; thrown at AzureTableJournalStorage.cs:1280.

Common situations: A config sentinel like -1 meant to mean 'unlimited' but the option does not support that; misbound integer from appsettings; arithmetic that underflowed.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/f4732338cac87b7e. Report an issue: GitHub.