---
title: ToKnownError (ExceptionHandler)
summary: Map an HTTP failure status and response content to a typed SAIF exception.
status: draft
owner: bendy
last_reviewed: 2026-09-15
library: SAIF.Web.API.Clients
reference_type: package
operation_id: OP-09
trigger: EnsureSuccessfulResponse step 4; also directly callable by consumers
---

# ToKnownError (ExceptionHandler)

`ExceptionHandler.ToKnownError` is the final step in translating an HTTP failure into a caller-meaningful domain exception, drawn from [SAIF.Web.API.Core](../../saif-web-api-core/overview.md)'s `SAIF.API.Exceptions.*` hierarchy.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-09 |
| **Trigger** | [EnsureSuccessfulResponse](ensure-successful-response.md) step 4; also directly callable by consumers (public static). |
| **Inputs** | `HttpStatusCode status`, raw response `content`. |
| **Outputs** | Always throws. |
| **Primary components** | `ExceptionHandler.ToKnownError(HttpStatusCode, string)` |
| **Entry point** | `src/SAIF.Web.API.Clients/ExceptionHandler.cs` |

## Steps

1. If `content` is non-empty, `JToken.Parse(content)` and iterate its tokens ([BR-CLI-008](../business-rules.md#br-cli-008-exception-message-source-preference)).
   - On failure: `catch { sb.Append(content); }` — a parse failure makes the raw content the message.
2. For each token whose `Path` (lower-cased) is one of `errormessage`, `exceptionmessage`, `message`, `usermessage`, append `token.First.ToString()` ([BR-CLI-008](../business-rules.md#br-cli-008-exception-message-source-preference)).
   - Matching is on the token path, so only top-level properties with those names are harvested. Multiple matches are concatenated as separate lines.
3. If nothing was harvested (blank builder), fall back to the raw `content` ([BR-CLI-008](../business-rules.md#br-cli-008-exception-message-source-preference)).
   - Guarantees a non-empty message whenever content was non-empty.
4. `switch (status)`: `404` → `NoMatchingDataException`; `403` or `401` → `SAIF.API.Exceptions.UnauthorizedAccessException`; `400` → `InvalidDataException`; default (all other statuses, including `0`) → `InternalServerError`. Set `HttpStatusCode = status` on the thrown instance ([BR-CLI-007](../business-rules.md#br-cli-007-http-status-to-exception-type-mapping)).
   - The thrown exception types are constructed in [SAIF.Web.API.Core](../../saif-web-api-core/overview.md) (`src/SAIF.Web.API.Core/SAIFException.cs`): each constructor calls the base `Exception(string)` constructor with a default message, and the `HttpStatusCode` property is set by object initializer — no further logic.
   - Always throws; never returns.

## Process flow

The following diagrams visualize this operation's control flow, split by concern so each renders at a readable width.

The first diagram shows message harvesting/fallback and the `404`/`401 or 403` status outcomes:

```mermaid
flowchart TD
	Start([ToKnownError called]) --> Parse[Parse content as JToken]
	Parse --> Harvest["Harvest<br>errormessage/<br>exceptionmessage/<br>message/usermessage<br>tokens"]
	Harvest --> Fallback{Message harvested?}
	Fallback -->|No| RawContent[Fall back to raw content]
	Fallback -->|Yes| Switch
	RawContent --> Switch{status?}
	Switch -->|404| NoMatch(["Throw<br>NoMatchingDataException"])
	Switch -->|401 or 403| Unauth(["Throw<br>UnauthorizedAccess<br>Exception"])
```

The second diagram shows the remaining `400` and `other` status outcomes:

```mermaid
flowchart TD
	Switch{status?} -->|400| Invalid(["Throw<br>InvalidDataException"])
	Switch -->|other| Internal(["Throw<br>InternalServerError"])
```

## Failure and edge-case behavior
- A non-JSON or malformed `content` falls back to the raw content as the exception message (step 1).
- Status codes other than `400`/`401`/`403`/`404` — including `0` (transport failure) — map to `InternalServerError`.

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

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