dotnet/orleans · error · ArgumentException
Azure Table partition keys must not contain '/', '\\', '#',
Error message
Azure Table partition keys must not contain '/', '\\', '#', '?', or control characters.
What it means
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.
Source
Thrown at src/Azure/Orleans.Journaling.AzureStorage/AzureTableJournalStorageOptions.cs:165
}
}
private static void ValidatePartitionKey(string partitionKey, string parameterName)
{
if (partitionKey.Length > 1024)
{
throw new ArgumentException(
"Azure Table partition keys must not exceed 1,024 characters.",
parameterName);
}
foreach (var character in partitionKey)
{
if (character is '/' or '\\' or '#' or '?'
or >= '\u0000' and <= '\u001F'
or >= '\u007F' and <= '\u009F')
{
throw new ArgumentException(
"Azure Table partition keys must not contain '/', '\\', '#', '?', or control characters.",
parameterName);
}
}
}
private static bool IsAsciiLetter(char character)
=> character is >= 'A' and <= 'Z' or >= 'a' and <= 'z';
/// <summary>
/// Configures the <see cref="TableServiceClient"/> using a connection string.
/// </summary>
public void ConfigureTableServiceClient(string connectionString)
{
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
CreateClient = ct => Task.FromResult(new TableServiceClient(connectionString, ClientOptions));
}
View on GitHub (pinned to fca799fa70)
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.
Example fix
// before options.GetPartitionKey = id => id.Value; // raw, may contain '/' // after options.GetPartitionKey = id => Uri.EscapeDataString(id.Value);
Defensive patterns
Strategy: validation
Validate before calling
static bool IsValidPartitionKey(string k) =>
k.Length <= 1024 && !k.Any(c => c is '/' or '\\' or '#' or '?' || c <= '\u001F' || c >= '\u007F' && c <= '\u009F'); Type guard
static bool IsPartitionKeySafe(string k) => !k.Any(c => c is '/' or '\\' or '#' or '?' || c <= '\u001F' || c >= '\u007F' && c <= '\u009F');
Prevention
- In custom mappers, always escape with Uri.EscapeDataString before returning.
- Reuse AzureTableJournalStorageOptions.GetDefaultPartitionKey for escaping.
- Never pass raw paths or URLs as partition keys.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Azure Table partition keys must not exceed 1,024 characters.
- Value cannot be null.
- The journal id must not be the default value.
- Key length {0} is too long to be an DynamoDB partition key.
- The journal id must not be the default value.
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/f84df5f6ca0132a9.
Report an issue: GitHub.