{"record":{"id":"f84df5f6ca0132a9","repo":"dotnet/orleans","slug":"azure-table-partition-keys-must-not-contain","errorCode":null,"errorMessage":"Azure Table partition keys must not contain '/', '\\\\', '#', '?', or control characters.","messagePattern":"Azure Table partition keys must not contain '/', '\\\\\\\\', '#', '\\?', or control characters\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorageOptions.cs","lineNumber":165,"sourceCode":"        }\n    }\n\n    private static void ValidatePartitionKey(string partitionKey, string parameterName)\n    {\n        if (partitionKey.Length > 1024)\n        {\n            throw new ArgumentException(\n                \"Azure Table partition keys must not exceed 1,024 characters.\",\n                parameterName);\n        }\n\n        foreach (var character in partitionKey)\n        {\n            if (character is '/' or '\\\\' or '#' or '?'\n                or >= '\\u0000' and <= '\\u001F'\n                or >= '\\u007F' and <= '\\u009F')\n            {\n                throw new ArgumentException(\n                    \"Azure Table partition keys must not contain '/', '\\\\', '#', '?', or control characters.\",\n                    parameterName);\n            }\n        }\n    }\n\n    private static bool IsAsciiLetter(char character)\n        => character is >= 'A' and <= 'Z' or >= 'a' and <= 'z';\n\n    /// <summary>\n    /// Configures the <see cref=\"TableServiceClient\"/> using a connection string.\n    /// </summary>\n    public void ConfigureTableServiceClient(string connectionString)\n    {\n        ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);\n        CreateClient = ct => Task.FromResult(new TableServiceClient(connectionString, ClientOptions));\n    }\n","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorageOptions.cs#L147-L183","documentation":"Thrown by ValidatePartitionKey when the computed partition key contains a character disallowed by Azure Tables: '/', '\\\\', '#', '?', or any control character (U+0000-U+001F or U+007F-U+009F). This guards custom mappers that may not escape such characters.","triggerScenarios":"A custom GetPartitionKey mapper returns a raw string containing '/', '\\', '#', '?', or a control character; the default mapper percent-encodes these so this normally only fires for user-supplied mappers.","commonSituations":"A custom mapper concatenates a path-like id with '/' separators; a mapper returns a JournalId.Value verbatim that contains a '#'; binary/control data leaks into the key.","solutions":["In your custom mapper, escape disallowed characters (Uri.EscapeDataString or a targeted replace) before returning.","Prefer reusing GetDefaultPartitionKey inside your custom mapper for the escaping step.","Strip or replace '/', '\\', '#', '?' and control chars at the source of the id."],"exampleFix":"// before\noptions.GetPartitionKey = id => id.Value; // raw, may contain '/'\n// after\noptions.GetPartitionKey = id => Uri.EscapeDataString(id.Value);","handlingStrategy":"validation","validationCode":"static bool IsValidPartitionKey(string k) =>\n    k.Length <= 1024 && !k.Any(c => c is '/' or '\\\\' or '#' or '?' || c <= '\\u001F' || c >= '\\u007F' && c <= '\\u009F');","typeGuard":"static bool IsPartitionKeySafe(string k) => !k.Any(c => c is '/' or '\\\\' or '#' or '?' || c <= '\\u001F' || c >= '\\u007F' && c <= '\\u009F');","tryCatchPattern":null,"preventionTips":["In custom mappers, always escape with Uri.EscapeDataString before returning.","Reuse AzureTableJournalStorageOptions.GetDefaultPartitionKey for escaping.","Never pass raw paths or URLs as partition keys."],"tags":["azure-table-storage","journaling","validation","partition-key","escaping"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}