> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hardwave.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Hardwave exception hierarchy, graph validation diagnostics, and runtime component faults

Hardwave uses a typed exception hierarchy for wiring and configuration errors, and a structured `Diagnostic` system for both pre-run validation and **runtime** component health events.

## Exception hierarchy

```
HardwaveError
├── TypeRegistrationError      # Registering a type name that already exists
├── TypeNotFoundError          # Looking up a type not in the registry
├── ComponentRegistrationError # Duplicate component name or invalid class
├── ComponentNotFoundError     # Looking up a component not in the registry
├── PortNotFoundError          # Port name not found on component
├── TypeMismatchError          # Incompatible types on a connection
├── PortDirectionError         # Connecting input→input or output→output
├── DuplicateConnectionError   # Second wire to a single-connection input port
├── MaxConnectionsExceededError # Port max_connections limit reached
├── PortConfigurationError     # Invalid aggregation declaration at registration
├── GraphValidationError       # Graph fails validation (carries Diagnostics)
├── SolverError                # Solver computation failure
├── SimulationError            # Engine-level failure (includes fault_mode=STOP)
├── SimulationResultError      # Accessing time-series on a steady-state result
└── DeserializationError       # Corrupt or incompatible serialized data
```

Premium components add a separate hierarchy under `PremiumError`:

```
PremiumError
├── PremiumNotConfiguredError  # configure() not called before sync()
├── PremiumAuthError           # Server rejected credentials
├── PremiumSyncError           # Manifest could not be fetched
└── PremiumSolveError          # Remote solve request failed
```

## Diagnostic levels

```python theme={null}
from hardwave.diagnostics import DiagnosticLevel

DiagnosticLevel.INFO     # Informational
DiagnosticLevel.WARNING  # Out of spec; simulation continues
DiagnosticLevel.ERROR    # Wiring/config error; blocks at validate()
DiagnosticLevel.FAULT    # Runtime catastrophic failure during simulation
```

Each `Diagnostic` carries:

| Field          | Description                                         |
| -------------- | --------------------------------------------------- |
| `level`        | `INFO`, `WARNING`, `ERROR`, or `FAULT`              |
| `code`         | Machine-readable code, e.g. `MOTOR_THERMAL_RUNAWAY` |
| `message`      | Human-readable description                          |
| `component_id` | Instance ID of the affected component               |
| `port_name`    | Port involved, if applicable                        |
| `suggestion`   | How to fix or mitigate                              |
| `step_index`   | Transient step index (runtime diagnostics)          |
| `timestamp`    | Simulation time in seconds (runtime diagnostics)    |
| `value`        | Measured value that triggered the diagnostic        |
| `threshold`    | Limit that was exceeded                             |

## Graph validation

`GraphValidationError` carries a full list of `Diagnostic` objects:

```python theme={null}
from hardwave.diagnostics import GraphValidationError, DiagnosticLevel

try:
    graph.validate()
except GraphValidationError as e:
    for d in e.diagnostics:
        print(f"[{d.level.value}] {d.code}: {d.message}")
        if d.suggestion:
            print(f"  → {d.suggestion}")
```

### Common wiring errors

| Error                         | Cause                              | Fix                                                |
| ----------------------------- | ---------------------------------- | -------------------------------------------------- |
| `PortNotFoundError`           | Port name typo                     | Check component port declarations                  |
| `TypeMismatchError`           | Incompatible signal types          | Use a converter component or fix the connection    |
| `PortDirectionError`          | Output connected to output         | Connect output → input only                        |
| `DuplicateConnectionError`    | Second wire to `input_port()`      | Use `aggregating_input_port()` or disconnect first |
| `MaxConnectionsExceededError` | Too many wires on aggregating port | Raise `max_connections` or remove a connection     |
| `INSUFFICIENT_CONNECTIONS`    | Fewer wires than `min_connections` | Add connections or lower the minimum               |
| `PortConfigurationError`      | `CUSTOM` without `aggregate=`      | Provide `aggregate=` or a built-in mode            |

### Validation checklist

Before calling `engine.run()`, ensure every required input port is:

1. Connected to an upstream output, **or**
2. Has a default value, **or**
3. Appears in the `inputs` dict passed to `run()` (and `validate()`)

## Runtime component faults

During simulation, components with fault rules emit `WARNING` and `FAULT` diagnostics. These are collected in `SimulationResult`. They do not raise exceptions unless `fault_mode=STOP`.

```python theme={null}
from hardwave.simulation import SimulationEngine, SimulationConfig, FaultMode

result = SimulationEngine(graph).run(inputs={...})

for d in result.get_warnings():
    print(d)

for d in result.get_faults():
    print(f"{d.code}: {d.message} (value={d.value}, limit={d.threshold})")

# Abort simulation on first FAULT
config = SimulationConfig(fault_mode=FaultMode.STOP)
try:
    engine.run(inputs={...}, config=config)
except SimulationError as e:
    print(e)  # e.g. MOTOR_THERMAL_RUNAWAY
```

### Built-in fault codes (stdlib)

**DCMotor**

| Code | Level   | Code string             |
| ---- | ------- | ----------------------- |
| 1    | WARNING | `MOTOR_THERMAL_HIGH`    |
| 2    | WARNING | `MOTOR_OVER_CURRENT`    |
| 100  | FAULT   | `MOTOR_THERMAL_RUNAWAY` |

**LiPoCell**

| Code | Level   | Code string           |
| ---- | ------- | --------------------- |
| 1    | WARNING | `CELL_LOW_SOC`        |
| 2    | WARNING | `CELL_HIGH_TEMP`      |
| 100  | FAULT   | `CELL_OVERDISCHARGE`  |
| 101  | FAULT   | `CELL_THERMAL_DAMAGE` |

See [Component Faults and Health](/guides/component-faults) for parameters, degraded output behaviour, and how to add faults to custom components.

## Simulation errors

| Error                   | When                                                    |
| ----------------------- | ------------------------------------------------------- |
| `SolverError`           | A solver raises during `solve()` (e.g. zero resistance) |
| `SimulationError`       | Engine failure, or first `FAULT` when `fault_mode=STOP` |
| `SimulationResultError` | Calling `get_time_series()` on a steady-state result    |

## Deserialization

`DeserializationError` is raised when loading a saved graph with an unknown component class, incompatible schema version, or corrupt JSON. Ensure all custom components are registered before calling `SimulationGraph.from_dict()`.
