{"record":{"id":"1914e3e9846527ec","repo":"dotnet/orleans","slug":"value-cannot-be-null","errorCode":null,"errorMessage":"Value cannot be null.","messagePattern":"Value cannot be null\\.","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorageOptions.cs","lineNumber":109,"sourceCode":"    /// retries. The exponential schedule starts at <see cref=\"MetadataOnlyConflictInitialBackoff\"/>\n    /// and never exceeds this value. Defaults to 200 ms.\n    /// </summary>\n    public TimeSpan MetadataOnlyConflictMaxBackoff { get; set; } = DEFAULT_METADATA_ONLY_CONFLICT_MAX_BACKOFF;\n    public static readonly TimeSpan DEFAULT_METADATA_ONLY_CONFLICT_MAX_BACKOFF = TimeSpan.FromMilliseconds(200);\n\n    /// <summary>\n    /// The optional delegate used to create a <see cref=\"TableServiceClient\"/> instance.\n    /// </summary>\n    internal Func<CancellationToken, Task<TableServiceClient>>? CreateClient { get; private set; }\n\n    internal string GetPartitionKeyForJournal(JournalId journalId)\n    {\n        if (journalId.IsDefault)\n        {\n            throw new ArgumentException(\"The journal id must not be the default value.\", nameof(journalId));\n        }\n\n        var mapper = GetPartitionKey ?? throw new ArgumentNullException(nameof(GetPartitionKey));\n        var partitionKey = mapper(journalId);\n        ArgumentException.ThrowIfNullOrWhiteSpace(partitionKey);\n        ValidatePartitionKey(partitionKey, nameof(partitionKey));\n        return partitionKey;\n    }\n\n    internal static string GetDefaultPartitionKey(JournalId journalId)\n    {\n        if (journalId.IsDefault)\n        {\n            throw new ArgumentException(\"The journal id must not be the default value.\", nameof(journalId));\n        }\n\n        // Percent-encoding escapes every character disallowed in partition keys ('/', '\\', '#', '?',\n        // control characters) and is reversible.\n        var partitionKey = Uri.EscapeDataString(journalId.Value);\n        ValidatePartitionKey(partitionKey, nameof(journalId));\n        return partitionKey;","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorageOptions.cs#L91-L127","documentation":"Thrown by GetPartitionKeyForJournal when the AzureTableJournalStorageOptions.GetPartitionKey delegate has been set to null. The property defaults to a built-in mapper (DefaultGetPartitionKey), so this only fires when application code explicitly assigns null. The check guards the partition-key pipeline before it ever touches Azure Tables.","triggerScenarios":"Calling code sets options.GetPartitionKey = null (or a config binder nulls it), then any operation that resolves a journal partition key (read, append, replace, list) invokes GetPartitionKeyForJournal and hits the null-coalescing throw at AzureTableJournalStorageOptions.cs:109.","commonSituations":"A developer overrides the partition-key mapper and later sets it to null to 'reset' it; an options validator or post-configuration step nulls the delegate; reflection/JSON config binding supplies null for the Func property.","solutions":["Remove the assignment that sets options.GetPartitionKey to null; leave the default mapper in place.","If you need a custom mapper, assign a non-null Func<JournalId, string> that returns a valid partition key.","Restore the default with options.GetPartitionKey = AzureTableJournalStorageOptions.GetDefaultPartitionKey (via the public property default)."],"exampleFix":"// before\noptions.GetPartitionKey = null;\n// after\n// (omit the line entirely, or:)\noptions.GetPartitionKey = journalId => AzureTableJournalStorageOptions.GetDefaultPartitionKey(journalId);","handlingStrategy":"validation","validationCode":"if (options.GetPartitionKey is null)\n    throw new InvalidOperationException(\"GetPartitionKey must not be null; leave default or set a mapper.\");","typeGuard":"static bool HasPartitionKeyMapper(AzureTableJournalStorageOptions o) => o.GetPartitionKey is not null;","tryCatchPattern":null,"preventionTips":["Never assign null to options.GetPartitionKey; to revert, assign the default mapper.","Add an IValidateOptions<AzureTableJournalStorageOptions> that asserts GetPartitionKey is non-null.","In post-configuration code, treat nulling the delegate as a programming error."],"tags":["azure-table-storage","journaling","configuration","argument-null","partition-key"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}