{"record":{"id":"8e76dfe092d5dd2b","repo":"dotnet/orleans","slug":"metadataonlyconflictmaxbackoff-must-be-non-negativ","errorCode":null,"errorMessage":"MetadataOnlyConflictMaxBackoff must be non-negative.","messagePattern":"MetadataOnlyConflictMaxBackoff must be non-negative\\.","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Journaling.AzureStorage/AzureBlobJournalStorage.cs","lineNumber":1147,"sourceCode":"            ArgumentNullException.ThrowIfNull(options);\n            ArgumentNullException.ThrowIfNull(blobClientProvider);\n\n            Logger = logger;\n            Options = options.Value;\n            ArgumentNullException.ThrowIfNull(Options);\n            if (Options.MaxMetadataOnlyConflictRetries < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(options), $\"{nameof(AzureBlobJournalStorageOptions.MaxMetadataOnlyConflictRetries)} must be non-negative.\");\n            }\n\n            if (Options.MetadataOnlyConflictInitialBackoff < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(options), $\"{nameof(AzureBlobJournalStorageOptions.MetadataOnlyConflictInitialBackoff)} must be non-negative.\");\n            }\n\n            if (Options.MetadataOnlyConflictMaxBackoff < TimeSpan.Zero)\n            {\n                throw new ArgumentOutOfRangeException(nameof(options), $\"{nameof(AzureBlobJournalStorageOptions.MetadataOnlyConflictMaxBackoff)} must be non-negative.\");\n            }\n\n            MimeType = mimeType;\n            JournalFormatKey = journalFormatKey;\n            BlobClientProvider = blobClientProvider;\n            Instruments = instruments;\n        }\n\n        public ILogger<AzureBlobJournalStorage> Logger { get; }\n\n        public AzureBlobJournalStorageOptions Options { get; }\n\n        public string? MimeType { get; }\n\n        public string? JournalFormatKey { get; }\n\n        public BlobClientProvider BlobClientProvider { get; }\n        public AzureBlobJournalStorageInstruments Instruments { get; }","sourceCodeStart":1129,"sourceCodeEnd":1165,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Journaling.AzureStorage/AzureBlobJournalStorage.cs#L1129-L1165","documentation":"Thrown during AzureBlobJournalStorageShared construction when AzureBlobJournalStorageOptions.MetadataOnlyConflictMaxBackoff is negative. This TimeSpan caps the exponential backoff used between metadata-only conflict retries. A negative cap is invalid; TimeSpan.Zero is the minimum sensible value.","triggerScenarios":"Setting options.MetadataOnlyConflictMaxBackoff to a value less than TimeSpan.Zero and then constructing the provider or shared storage object. Validation runs in the AzureBlobJournalStorageShared constructor.","commonSituations":"Misconfiguring from JSON where the field is omitted and a default-fallback sets a negative value; setting max backoff lower than initial backoff and entering negative territory via subtraction; copy-paste error from initial backoff.","solutions":["Set MetadataOnlyConflictMaxBackoff to a positive value such as the default 200 ms, or TimeSpan.Zero.","Ensure max backoff >= initial backoff to keep the exponential schedule meaningful.","Register an IValidateOptions<AzureBlobJournalStorageOptions> to fail fast at startup."],"exampleFix":"// before\noptions.MetadataOnlyConflictMaxBackoff = TimeSpan.FromMilliseconds(-1);\n\n// after\noptions.MetadataOnlyConflictMaxBackoff = TimeSpan.FromMilliseconds(200);","handlingStrategy":"validation","validationCode":"if (options.MetadataOnlyConflictMaxBackoff < TimeSpan.Zero)\n    throw new ArgumentOutOfRangeException(nameof(options.MetadataOnlyConflictMaxBackoff));\n// ensure max >= initial\nservices.AddOptions<AzureBlobJournalStorageOptions>()\n    .Validate(o => o.MetadataOnlyConflictMaxBackoff >= TimeSpan.Zero\n        && o.MetadataOnlyConflictMaxBackoff >= o.MetadataOnlyConflictInitialBackoff,\n        \"MaxBackoff must be non-negative and >= InitialBackoff\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register an IValidateOptions that checks both non-negativity and max >= initial.","Avoid computing backoff values via subtraction that can go negative.","Document the default (200 ms) so operators know the expected range."],"tags":["azure-blob-storage","configuration","validation","argument"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}