---
title: EnsureSuccessfulResponse (ExceptionHandler)
summary: Guard a response's success status and route failures to exception mapping.
status: draft
owner: bendy
last_reviewed: 2026-09-15
library: SAIF.Web.API.Clients
reference_type: package
operation_id: OP-08
trigger: GetJsonResponse step 11
---

# EnsureSuccessfulResponse (ExceptionHandler)

`ExceptionHandler.EnsureSuccessfulResponse` is the guard that decides whether a completed HTTP response should be converted into a typed exception, and — if so — selects the error text to carry.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-08 |
| **Trigger** | [GetJsonResponse](get-json-response.md) step 11. |
| **Inputs** | `IRestResponse response`. |
| **Outputs** | None (void), or a thrown `SAIFException`. |
| **Primary components** | `ExceptionHandler.EnsureSuccessfulResponse(IRestResponse)` |
| **Entry point** | `src/SAIF.Web.API.Clients/ExceptionHandler.cs` |

## Steps

1. Cast `response.StatusCode` to `int`.
   - Transport failure gives `0`.
2. If `status < 200` or `status >= 400`: proceed. Otherwise return normally ([BR-CLI-006](../business-rules.md#br-cli-006-non-success-response-failure-conversion)).
   - 3xx redirect statuses are treated as success and pass the guard, since only `< 200` and `>= 400` fail. Status `0` fails the guard (`0 < 200`).
3. Select the error text via `GetContent(response)` ([BR-CLI-017](../business-rules.md#br-cli-017-failure-message-source-selection)).
   - `GetContent` returns `response.Content` when non-blank; otherwise — when `ErrorMessage` is non-blank or `ErrorException` is non-null — it enters a nested branch whose first test is `if (response.ErrorMessage.IsNullOrWhiteSpace()) return response.ErrorMessage;`, which can only return a blank string; otherwise, for non-`BadRequest` statuses, it returns `"{code} - {statusDescription}"`; otherwise `string.Empty`*.
   - The nested `ErrorMessage` test is inverted relative to its enclosing guard, so the `ErrorException.Message` path is effectively unreachable and a transport-level failure with no `Content` yields a blank error message*.
4. Throw the mapped exception.
   - Embedded logic: parse the content for a known message field, then switch on the status code to select the exception type.

   > **Origin**: This step is implemented in [ToKnownError](to-known-error.md) (`SAIF.Web.API.Clients`) and executed on behalf of this operation.
   - Never returns.

## Process flow

```mermaid
flowchart TD
	Start(["EnsureSuccessfulResponse<br>called"]) --> Cast[Cast StatusCode to int]
	Cast --> Range{"status &lt; 200 or &gt;=<br>400?"}
	Range -->|No| EndOk([Return normally])
	Range -->|Yes| Content["GetContent: select error<br>text"]
	Content --> Throw(["ToKnownError: throw<br>mapped SAIFException"])
```

## Failure and edge-case behavior
- A 3xx redirect status passes the guard as success even though it is not a completed 2xx response.
- The inverted inner condition in `GetContent` makes the `ErrorException.Message` path unreachable, so a transport-level failure with no `Content` produces a blank exception message*.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

> **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`
