---
title: ExceptionHandler
summary: API reference for ExceptionHandler.
status: draft
owner: bendy
last_reviewed: 2026-09-15
library: SAIF.Web.API.Clients.35
reference_type: package
---

# ExceptionHandler

`ExceptionHandler` is the static error-translation type that `JsonHttpClient` calls after every request to convert an unsuccessful HTTP response into a specific, typed `SAIFException` subtype sourced from `SAIF.Web.API.Core`'s exception taxonomy, so callers can catch and branch on strongly-typed error conditions instead of inspecting raw HTTP status codes.

## Purpose
- Decide, from an `IRestResponse`'s status code, whether a request succeeded (200–399) or failed ([BR-16](../../business-rules.md#br-16-success-status-range)).
- Extract a human-readable error message: the response body when present; otherwise, a nonstandard fallback in `GetContent` that does not reliably use RestSharp's `ErrorMessage`/`ErrorException`, and only synthesizes a status line when both are absent ([BR-17](../../business-rules.md#br-17-error-message-source-selection)).
- Map the HTTP status code to a specific `SAIFException` subtype: `NoMatchingDataException` (404), `UnauthorizedAccessException` (401/403), `InvalidDataException` (400), or `InternalServerError` (all other failure codes) ([BR-20](../../business-rules.md#br-20-http-status-to-exception-type-mapping)).

## Context
- Namespace: `SAIF.Web.API.Clients`
- Assembly/package: `SAIF.Web.API.Clients` (net35 build variant; not shipped by the current package definition — see [Overview](../../overview.md))

## Public members
| Member | Signature | Purpose |
| --- | --- | --- |
| `EnsureSuccessfulResponse` | `public static void EnsureSuccessfulResponse(IRestResponse response)` | Entry point called by `JsonHttpClient`; throws a typed `SAIFException` subtype when the status code is `<200` or `>=400`, otherwise returns normally ([BR-16](../../business-rules.md#br-16-success-status-range)). |
| `ToKnownError` | `public static void ToKnownError(HttpStatusCode statusCode, string content)` | Maps a status code and response body directly to a specific `SAIFException` subtype and throws it; callable independently of `EnsureSuccessfulResponse` ([BR-18](../../business-rules.md#br-18-recognized-error-property-names), [BR-19](../../business-rules.md#br-19-fallback-to-raw-body-on-parse-failure), [BR-20](../../business-rules.md#br-20-http-status-to-exception-type-mapping)). |

## Non-public implementation details
| Member | Signature | Purpose |
| --- | --- | --- |
| `GetContent` | `private static string GetContent(IRestResponse response)` | Non-public helper returning `response.Content` when nonblank; otherwise `string.Empty` if only `ErrorMessage` is nonblank (with `ErrorException` null), `ErrorMessage` (blank) if only `ErrorException` is non-null, `ErrorException.Message` when both are present, a synthesized `"{code} - {StatusDescription}"` when both are absent and the status is not 400, and `string.Empty` otherwise — a defect-like fallback chain rather than a clean precedence order ([BR-17](../../business-rules.md#br-17-error-message-source-selection)). |

## Behavioral notes
- The full step-by-step error-translation logic is documented in [Translate HTTP failure to typed exception](../../operations/op-03-translate-http-failure.md).
- Recognized structured-error property names are `errormessage`, `exceptionmessage`, `message`, and `usermessage`, matched case-insensitively against parsed JSON tokens ([BR-18](../../business-rules.md#br-18-recognized-error-property-names)).
- `GetContent` uses `SAIF.Common.Extensions.IsNullOrWhiteSpace` from `SAIF.Framework.Common` to decide whether a candidate message is usable.

## Constraints and usage notes
- Error responses are surfaced verbatim: if the remote API returns sensitive detail in an error body, this type propagates it into the exception message without redaction.*
- `GetContent`'s fallback logic when the response body is blank appears to be a defect rather than designed behavior: a lone nonblank `ErrorMessage` (with no `ErrorException`) is discarded in favor of `string.Empty`, and a lone `ErrorException` (with a blank `ErrorMessage`) is discarded in favor of the blank `ErrorMessage`, so `ErrorException.Message` is only ever surfaced when both fields happen to be set. See [BR-17](../../business-rules.md#br-17-error-message-source-selection) for the verified branch-by-branch behavior.

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts.

## Sources
- src/SAIF.Web.API.Clients/ExceptionHandler.cs
- src/SAIF.Web.API.Core/SAIFException.cs
