dotnet/orleans · error · ArgumentOutOfRangeException
MaxMetadataOnlyConflictRetries must be non-negative.
Error message
MaxMetadataOnlyConflictRetries must be non-negative.
What it means
Thrown during AzureBlobJournalStorageShared construction when AzureBlobJournalStorageOptions.MaxMetadataOnlyConflictRetries is negative. This option caps how many times the storage layer retries in place after a metadata-only ETag conflict before falling back to full recovery via InconsistentStateException. A negative value is meaningless and is rejected at construction time.
Source
Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureBlobJournalStorage.cs:1137
{
public AzureBlobJournalStorageShared(
ILogger<AzureBlobJournalStorage> logger,
IOptions<AzureBlobJournalStorageOptions> options,
BlobClientProvider blobClientProvider,
AzureBlobJournalStorageInstruments instruments,
string? mimeType = null,
string? journalFormatKey = null)
{
ArgumentNullException.ThrowIfNull(logger);
ArgumentNullException.ThrowIfNull(options);
ArgumentNullException.ThrowIfNull(blobClientProvider);
Logger = logger;
Options = options.Value;
ArgumentNullException.ThrowIfNull(Options);
if (Options.MaxMetadataOnlyConflictRetries < 0)
{
throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureBlobJournalStorageOptions.MaxMetadataOnlyConflictRetries)} must be non-negative.");
}
if (Options.MetadataOnlyConflictInitialBackoff < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureBlobJournalStorageOptions.MetadataOnlyConflictInitialBackoff)} must be non-negative.");
}
if (Options.MetadataOnlyConflictMaxBackoff < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(options), $"{nameof(AzureBlobJournalStorageOptions.MetadataOnlyConflictMaxBackoff)} must be non-negative.");
}
MimeType = mimeType;
JournalFormatKey = journalFormatKey;
BlobClientProvider = blobClientProvider;
Instruments = instruments;
}
View on GitHub (pinned to fca799fa70)
Solutions
- Set MaxMetadataOnlyConflictRetries to 0 (disable in-place retry) or a positive integer; keep the default of 5 unless you have measured conflict rates.
- If you intended 'retry forever', raise the cap rather than using a negative value; the design requires a bounded retry count.
- Validate the option in your configuration validator (IValidateOptions<AzureBlobJournalStorageOptions>) so misconfigurations surface at startup, not at first use.
Example fix
// before options.MaxMetadataOnlyConflictRetries = -1; // after options.MaxMetadataOnlyConflictRetries = 0; // disable in-place retry; always go through recovery
Defensive patterns
Strategy: validation
Validate before calling
if (options.MaxMetadataOnlyConflictRetries < 0)
throw new ArgumentOutOfRangeException(nameof(options.MaxMetadataOnlyConflictRetries), "Must be non-negative.");
// or register IValidateOptions<AzureBlobJournalStorageOptions>:
// services.AddOptions<AzureBlobJournalStorageOptions>().ValidateDataAnnotations(); Prevention
- Bind options with .Validate(...) so invalid values surface at startup.
- Never use negative sentinels; use 0 to disable and a high cap for aggressive retry.
- Add a startup health check that constructs the provider to fail fast on bad config.
When it happens
Trigger: Constructing AzureBlobJournalStorageShared (directly or via the DI provider) after setting options.MaxMetadataOnlyConflictRetries to a value less than 0. Validation runs in the shared-state constructor before any storage operation.
Common situations: Setting the option to -1 intending 'retry forever' (not supported); misreading the default of 5 and setting it to a sentinel negative value; loading options from configuration with a typo that yields a negative integer.
Related errors
- MetadataOnlyConflictInitialBackoff must be non-negative.
- MetadataOnlyConflictMaxBackoff must be non-negative.
- Journal metadata property names must not contain null charac
- The journal id must not be the default value.
- Value cannot be null. (Parameter 'createClientCallback')
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/c63ddc2e928825fa.
Report an issue: GitHub.