dotnet/orleans · error · ArgumentException

Unexpected exception type {exception.GetType().FullName}

Error message

Unexpected exception type {exception.GetType().FullName}

What it means

ArgumentException from AzureTableUtils.PrintStorageException when the supplied exception is not a RequestFailedException (the Azure SDK's unified failure type). The helper expects to format Message/Status/ErrorCode from RequestFailedException; anything else is a programming contract violation and is rejected.

Source

Thrown at src/Azure/Shared/Storage/AzureTableUtils.cs:226

            // Remove any characters that can't be used in Azure PartitionKey or RowKey values
            // http://www.jamestharpe.com/web-development/azure-table-service-character-combinations-disallowed-in-partitionkey-rowkey/
            key = key
                .Replace('/', '_')        // Forward slash
                .Replace('\\', '_')       // Backslash
                .Replace('#', '_')        // Pound sign
                .Replace('?', '_');       // Question mark

            if (key.Length >= 1024)
                throw new ArgumentException(string.Format("Key length {0} is too long to be an Azure table key. Key={1}", key.Length, key));

            return key;
        }

        internal static string PrintStorageException(Exception exception)
        {
            if (exception is not RequestFailedException storeExc)
            {
                throw new ArgumentException($"Unexpected exception type {exception.GetType().FullName}");
            }

            return $"Message = {storeExc.Message}, HTTP Status = {storeExc.Status}, HTTP Error Code = {storeExc.ErrorCode}.";
        }

        internal static string PointQuery(string partitionKey, string rowKey)
        {
            return TableClient.CreateQueryFilter($"(PartitionKey eq {partitionKey}) and (RowKey eq {rowKey})");
        }

        internal static string RangeQuery(string partitionKey, string minRowKey, string maxRowKey)
        {
            return TableClient.CreateQueryFilter($"((PartitionKey eq {partitionKey}) and (RowKey ge {minRowKey})) and (RowKey le {maxRowKey})");
        }

    }
}

View on GitHub (pinned to fca799fa70)

Solutions

  1. Type-check before calling: if (exc is RequestFailedException rfe) PrintStorageException(rfe); else exc.ToString().
  2. Confirm the Azure.Data.Tables SDK version referenced matches what Orleans expects; a stale StorageException-throwing library will never match.
  3. Do not route OperationCanceledException or generic exceptions through this formatter.

Example fix

// before
var detail = AzureTableUtils.PrintStorageException(ex); // throws if not RequestFailedException

// after
var detail = ex is RequestFailedException rfe
    ? AzureTableUtils.PrintStorageException(rfe)
    : ex.ToString();
Defensive patterns

Strategy: type-guard

Validate before calling

var detail = exc is RequestFailedException rfe
    ? AzureTableUtils.PrintStorageException(rfe)
    : exc.ToString();

Type guard

static bool IsAzureStorageException(Exception ex) => ex is RequestFailedException;

Try / catch

try { /* azure op */ }
catch (RequestFailedException ex) { Log(AzureTableUtils.PrintStorageException(ex)); throw; }
catch (Exception ex) { Log(ex.ToString()); throw; }

Prevention

When it happens

Trigger: Passing a non-Azure exception (TimeoutException, OperationCanceledException, SerializationException, etc.) to PrintStorageException. This usually happens in a catch block that assumed the caught exception was from the storage SDK.

Common situations: A catch (Exception ex) that feeds ex into PrintStorageException without first checking the type, or after a dependency upgrade changed which exception type the SDK throws (e.g. older WindowsAzure.Storage threw StorageException; the current Azure.Data.Tables throws RequestFailedException). Mismatched SDK versions.

Related errors


AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13). Data as JSON: /api/errors/8f6e3520bce78cb3. Report an issue: GitHub.