dotnet/orleans · error · ArgumentOutOfRangeException

MetadataOnlyConflictInitialBackoff must be non-negative.

Error message

MetadataOnlyConflictInitialBackoff must be non-negative.

What it means

AzureTableJournalStorageOptions.MetadataOnlyConflictInitialBackoff was set to a negative TimeSpan. The constructor (AzureTableJournalStorage.cs:1283) requires it non-negative (TimeSpan.Zero is allowed and means retry immediately). The argument blamed is `options`.

Source

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

            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; }

        public AzureTableJournalStorageOptions Options { get; }

        public string? JournalFormatKey { get; }

View on GitHub (pinned to fca799fa70)

Solutions

  1. Set MetadataOnlyConflictInitialBackoff to TimeSpan.Zero or a positive value (default 10 ms).
  2. Use TimeSpan.Zero when you want immediate retries.
  3. Validate via IValidateOptions<T> at startup.

Example fix

// before
options.MetadataOnlyConflictInitialBackoff = TimeSpan.FromMilliseconds(-5);

// after
options.MetadataOnlyConflictInitialBackoff = AzureTableJournalStorageOptions.DEFAULT_METADATA_ONLY_CONFLICT_INITIAL_BACKOFF;
Defensive patterns

Strategy: validation

Validate before calling

if (options.MetadataOnlyConflictInitialBackoff < TimeSpan.Zero)
    throw new ArgumentOutOfRangeException(nameof(options.MetadataOnlyConflictInitialBackoff), "Must be non-negative");

Type guard

static bool IsValidBackoff(TimeSpan v) => v >= TimeSpan.Zero;

Prevention

When it happens

Trigger: Configuring MetadataOnlyConflictInitialBackoff < TimeSpan.Zero; thrown at AzureTableJournalStorage.cs:1285.

Common situations: Config parser produced a negative TimeSpan; a formula subtracted delays and underflowed; confusion between 'no delay' (Zero) and negative.

Related errors


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