{"record":{"id":"c63ddc2e928825fa","repo":"dotnet/orleans","slug":"maxmetadataonlyconflictretries-must-be-non-negativ","errorCode":null,"errorMessage":"MaxMetadataOnlyConflictRetries must be non-negative.","messagePattern":"MaxMetadataOnlyConflictRetries must be non-negative\\.","errorType":"validation","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Journaling.AzureStorage/AzureBlobJournalStorage.cs","lineNumber":1137,"sourceCode":"    {\n        public AzureBlobJournalStorageShared(\n            ILogger<AzureBlobJournalStorage> logger,\n            IOptions<AzureBlobJournalStorageOptions> options,\n            BlobClientProvider blobClientProvider,\n            AzureBlobJournalStorageInstruments instruments,\n            string? mimeType = null,\n            string? journalFormatKey = null)\n        {\n            ArgumentNullException.ThrowIfNull(logger);\n            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","sourceCodeStart":1119,"sourceCodeEnd":1155,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Journaling.AzureStorage/AzureBlobJournalStorage.cs#L1119-L1155","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\noptions.MaxMetadataOnlyConflictRetries = -1;\n\n// after\noptions.MaxMetadataOnlyConflictRetries = 0; // disable in-place retry; always go through recovery","handlingStrategy":"validation","validationCode":"if (options.MaxMetadataOnlyConflictRetries < 0)\n    throw new ArgumentOutOfRangeException(nameof(options.MaxMetadataOnlyConflictRetries), \"Must be non-negative.\");\n// or register IValidateOptions<AzureBlobJournalStorageOptions>:\n// services.AddOptions<AzureBlobJournalStorageOptions>().ValidateDataAnnotations();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"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"}