# Error Handling

## Recoverable Errors

Recoverable errors represent expected faults. Similar to Rust, Sway expresses recoverable errors by using the `std::result::Result` enum, letting you propagate or transform the error without immediately reverting the transaction.

To learn more about expressing and handling recoverable errors, see the chapter on [`Result<T, E>` enum](commonly_used_library_types.md#resultt-e).

## Irrecoverable Errors

Irrecoverable errors indicate bugs or violated invariants. They trigger a VM-wide revert that atomically rolls back every state change in the transaction, and it cannot be caught or handled in Sway code, signaling that the program cannot sensibly continue.

### `panic` Expression

The recommended way of expressing an irrecoverable errors is to use the `panic` expression:

```sway
if some_error_occurred {
    panic "Some error has occurred.";
}
```

At runtime, the `panic` expression aborts and reverts the execution of the entire program. At compile time, for each `panic` encountered in code, Sway compiler will generate a unique revert code and create an entry in the ABI JSON `errorCodes` section. The generated `errorCodes` entry will contain the information about source location at which the `panic` occurs, as well as the error message.

**This mechanism allows for getting a rich troubleshooting information, without an additional on-chain cost.** The generated bytecode will contain only the revert instruction, and the remaining information, the error message and the error location, are stored off-chain, in the ABI JSON file.

For example, let's assume that the above code is situated in the module `some_module`, contained within the version `v1.2.3` of the package `some_package`.

At runtime, the `panic` will result in a compiler generated revert code, e.g., 18446744069414584323. At compile time, an entry similar to this will be added to the ABI JSON `errorCodes` section:

```json
"errorCodes": {
    "18446744069414584323": {
        "pos": {
          "pkg": "some_package@1.2.3",
          "file": "some_module.sw",
          "line": 13,
          "column": 9
        },
        "logId": null,
        "msg": "Some error has occurred."
    },
}
```

Rust and TypeScript SDK, as well as `forc test`, recognize revert codes generated from `panic` expressions. E.g., if a Sway unit test fails because of a revert caused by the above `panic` line, the `forc test` will display the following:

```console
test some_test, "path/to/failing/test.sw":42
    revert code: ffffffff00000003
    ├─ panic message: Some error has occurred.
    └─ panicked in:   some_package@1.2.3, src/some_module.sw:13:9
```

### Error Types

Passing textual error messages directly as a `panic` argument is the most convenient way to provide a helpful error message. It is sufficient for many use-cases. However, often we want:

- to provide an additional runtime information about the error.
- group a certain family of errors together.

For these use-cases, you can use _error types_. Error types are enums annotated with the `#[error_type]` attribute, whose all variants are attributed with the `#[error(m = "<error message>")]` attributes. Each variant represent a particular error, and the enum itself the family of errors. The convention is to postfix the names of error type enums with `Error`.

For example, let's assume we are checking if a provided `Identity` has certain access rights to our contract. The error type enum representing access rights violations could look like:

```sway
#[error_type]
pub enum AccessRightError {
    #[error(m = "The provided identity is not an administrator.")]
    NotAnAdmin: Identity,
    #[error(m = "The provided identity is not an owner.")]
    NotAnOwner: Identity,
    #[error(m = "The provided identity does not have write access.")]
    NoWriteAccess: Identity,
}
```

where each `Identity` represents the actual, provided identity.

In code, we can now check for access rights and panic if they are violated:

```sway
fn do_something_that_requires_admin_access(admin: Identity) {
    if !is_admin(admin) {
        panic AccessRightError::NotAnAdmin(admin);
    }

    // ...
}
```

Assuming we have a failing test for the above function, the test output will show the error message, but also the provided `Identity`. E.g.:

```console
test some_test_for_admin_access, "path/to/failing/test.sw":42
    revert code: ffffffff00000007
    ├─ panic message: The provided identity is not an administrator.
    ├─ panic value:   NotAnAdmin(Address(Address()))
    └─ panicked in:   some_other_package@0.1.0, src/admin_module.sw:11:9
```
