---
title: Exception diagnostics formatting
summary: Builds a human-readable diagnostic string for an exception, recursing through inner exceptions and special-casing the SAIF custom exception type.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Presentation.ConsoleApplication
reference_type: package
operation_id: OP-CA-003
trigger: Downstream error-handling code catches an exception and calls GetExceptionInfo(ex)
---

# Exception diagnostics formatting

Downstream applications call `GetExceptionInfo` from a `Catch` block to turn an exception (and its full inner-exception chain) into one formatted, human-readable string suitable for console output or a log file, without each application re-implementing exception reflection logic.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CA-003 |
| **Trigger** | Downstream error-handling code catches an `Exception` and calls `GetExceptionInfo(ex)` |
| **Inputs** | `ex As Exception` |
| **Outputs** | Formatted diagnostic `String` |
| **Primary components** | `clsConsoleBase.GetExceptionInfo` |
| **Entry point** | `Presentation\SAIF.Presentation.ConsoleApplication\clsConsoleBase.vb` |

## Steps

1. **Recurse into any inner exception first.** If `ex.InnerException` is not `Nothing`, `GetExceptionInfo` calls itself recursively on the inner exception and prepends the resulting formatted text to the output before formatting `ex` itself.
2. **Inspect the exception's runtime type name.** `GetExceptionInfo` compares `ex.GetType.Name.ToUpper` against the literal `"CLSSAIFEXCEPTION"`.
3. **If the type name matches `clsSAIFException`:** the method reflects over all public properties of the exception's runtime type via `System.Reflection.PropertyInfo` and appends a `"<PropertyName>:  <PropertyValue>"` line for each one.*
   - This means any public property exposed by the framework's custom exception type (not imported or declared in this library) is surfaced automatically, without this library needing to know its shape in advance.*
4. **Otherwise (any other exception type):** the method appends three fixed lines — `Message`, `Source`, and `Stack Trace` (the last spanning multiple lines via `ex.StackTrace`).
5. **Append a separator.** Every call (recursive or not) appends a line of dashes (`"-----------------------"`) after its own formatted block.
6. **Return the accumulated string**, which is inner-exception text (if any) followed by the current exception's formatted block and separator.

## Process flow

The following diagram visualizes the recursive inner-exception walk.

```mermaid
flowchart TD
	Start([GetExceptionInfo called with ex]) --> HasInner{ex.InnerException<br>is not Nothing?}
	HasInner -->|Yes| Recurse[Recursively format<br>inner exception first]
	HasInner -->|No| CheckType
	Recurse --> CheckType{Type name is<br>CLSSAIFEXCEPTION?}
	CheckType -->|Yes| ReflectProps[Reflect public properties<br>and format each as Name: Value]
	CheckType -->|No| StdFields[Format Message, Source,<br>Stack Trace]
	ReflectProps --> Separator[Append dashed separator]
	StdFields --> Separator
	Separator --> Return([Return accumulated string])
```

## Failure and edge-case behavior

- Exceptions with a deep `InnerException` chain produce a proportionally long string; there is no recursion depth limit or cycle guard.*
- The `clsSAIFException` type-name check is a literal, case-normalized string comparison (`"CLSSAIFEXCEPTION"`), not a `TypeOf`/`Is` check, so any exception type whose runtime type name happens to match that literal — regardless of namespace or assembly — is treated as the SAIF custom exception and reflected instead of using the standard `Message`/`Source`/`StackTrace` fields.*
- Reflection over the custom exception's public properties will throw if a property getter itself throws; this is not caught within `GetExceptionInfo`.*

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

## Related documentation

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

## Sources

- `Presentation\SAIF.Presentation.ConsoleApplication\clsConsoleBase.vb`
