Skip to content

Error Mapping Reference

MonadicSharp.Azure maps every Azure SDK exception to a typed AzureError value. No exception ever escapes the library boundary — callers always receive Result<T> or Option<T>.

CosmosDB

Azure ExceptionHTTP StatusMonadicSharp ErrorAdditional Properties
CosmosException (404)404AzureError.NotFoundResourceType, ResourceId
CosmosException (409)409AzureError.ConflictResourceId
CosmosException (412)412AzureError.ConcurrencyConflictCurrentETag, ExpectedETag
CosmosException (429)429AzureError.RateLimitRetryAfter
CosmosException (503)503AzureError.ServiceUnavailable
CosmosException (408)408AzureError.Timeout
Any other CosmosExceptionvariesAzureError.UnexpectedStatusCode, ActivityId

Service Bus

Azure ExceptionHTTP StatusMonadicSharp ErrorAdditional Properties
ServiceBusException (MessageLockLost)410AzureError.LockLostEntityPath
ServiceBusException (MessageSizeExceeded)413AzureError.MessageTooLargeMaxSizeInBytes
ServiceBusException (QuotaExceeded)429AzureError.QuotaExceededEntityPath
ServiceBusException (ServiceTimeout)408AzureError.Timeout
ServiceBusException (MessagingEntityNotFound)404AzureError.NotFoundEntityPath
ServiceBusException (Unauthorized)401AzureError.Unauthorized
ServiceBusException (other)500AzureError.UnexpectedReason

Blob Storage

Azure ExceptionHTTP StatusMonadicSharp ErrorAdditional Properties
RequestFailedException (404)404AzureError.NotFoundBlobName, ContainerName
RequestFailedException (409 — BlobAlreadyExists)409AzureError.ConflictBlobName
RequestFailedException (412)412AzureError.ConcurrencyConflictCurrentETag
RequestFailedException (403)403AzureError.Forbidden
RequestFailedException (401)401AzureError.Unauthorized
RequestFailedException (429)429AzureError.RateLimitRetryAfter
RequestFailedException (other)variesAzureError.UnexpectedErrorCode, Status

Key Vault

Azure ExceptionHTTP StatusMonadicSharp ErrorAdditional Properties
RequestFailedException (404)404AzureError.NotFoundSecretName
RequestFailedException (403)403AzureError.ForbiddenSecretName
RequestFailedException (401)401AzureError.Unauthorized
RequestFailedException (429)429AzureError.RateLimitRetryAfter
RequestFailedException (409 — SecretDisabled)409AzureError.ConflictSecretName
RequestFailedException (other)variesAzureError.UnexpectedErrorCode

Azure OpenAI

Azure ExceptionHTTP StatusMonadicSharp ErrorAdditional Properties
RequestFailedException (429)429AzureOpenAiError.RateLimitRetryAfter, DeploymentName
RequestFailedException (404)404AzureOpenAiError.DeploymentNotFoundDeploymentName
RequestFailedException (400 — content_filter)400AzureOpenAiError.ContentFilteredFilterCategory
RequestFailedException (400 — context_length_exceeded)400AzureOpenAiError.ContextLengthExceededMaxTokens
RequestFailedException (401)401AzureOpenAiError.Unauthorized
RequestFailedException (503)503AzureOpenAiError.ServiceUnavailable
RequestFailedException (other)variesAzureOpenAiError.UnexpectedErrorCode

AzureError hierarchy

Error (MonadicSharp base)
└── AzureError
    ├── AzureError.NotFound
    ├── AzureError.Conflict
    ├── AzureError.ConcurrencyConflict
    ├── AzureError.RateLimit
    ├── AzureError.Timeout
    ├── AzureError.Unauthorized
    ├── AzureError.Forbidden
    ├── AzureError.ServiceUnavailable
    ├── AzureError.QuotaExceeded
    ├── AzureError.LockLost
    ├── AzureError.MessageTooLarge
    └── AzureError.Unexpected
        └── AzureOpenAiError (extends AzureError.Unexpected)
            ├── AzureOpenAiError.RateLimit
            ├── AzureOpenAiError.DeploymentNotFound
            ├── AzureOpenAiError.ContentFiltered
            └── AzureOpenAiError.ContextLengthExceeded

Handling specific error types

csharp
var result = await container.ReadItemMonadicAsync<Order>(id, partitionKey);

return result.Match(
    onSuccess: order => Ok(order),
    onFailure: error => error switch
    {
        AzureError.NotFound             => NotFound(),
        AzureError.ConcurrencyConflict  => Conflict("Item was modified by another process."),
        AzureError.RateLimit r          => StatusCode(429, $"Retry after {r.RetryAfter.TotalSeconds}s"),
        _                               => StatusCode(500, error.Message)
    });

Customising the mapping

Provide a custom IAzureErrorMapper to override or extend the default behavior:

csharp
public class MyCosmosErrorMapper : IAzureErrorMapper<CosmosException>
{
    public Error Map(CosmosException ex) => ex.StatusCode switch
    {
        HttpStatusCode.NotFound    => AzureError.NotFound with { ResourceId = ex.ActivityId },
        HttpStatusCode.Conflict    => new MyDomainConflictError(ex.Message),
        _                          => AzureError.Unexpected.From(ex)
    };
}

// Registration
builder.Services.AddSingleton<IAzureErrorMapper<CosmosException>, MyCosmosErrorMapper>();

The custom mapper is injected into the relevant extension methods automatically via DI.

Released under the MIT License.