Kotlin doesn't support [checked exceptions](https://kotlinlang.org/docs/exceptions.html#checked-exceptions).
This simplifies and streamlines error handling, because you can choose to
handle only those exceptions that are potentially recoverable. And because you
don't have to explicitly handle every possible exception, your code is less
cluttered and consequently, remains more focused on its primary purpose.

Recoverable failures are issues that a developer can address from their end.
For example, if an ID used in a call is not valid, the API throws a
`HomeException` with an `invalid data` message. The app developer can then
choose to either remove that ID from their cache or show the user a message
like "Structure not found".

An example of how one might handle a recoverable failure:  

    val result =
       try {
         homeManager.requestPermissions()
       } catch (e: HomeException) {
         PermissionsResult(
           PermissionsResultStatus.ERROR,
           "Got HomeException with error: ${e.message}",
         )
       }

<br />

Any method in the Home APIs can throw a
[`HomeException`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeException), so we recommend that you use a `try-catch` block to
catch `HomeException` on all calls.

When handling `HomeException`, check its
[`error.code`](https://developers.home.google.com/apis/android/reference/kotlin/com/google/home/HomeError#code()) and [`error.message`](https://developers.home.google.com/apis/android/reference/kotlin/com/google/home/HomeError#message()) fields to learn what went wrong. There may be sub-error codes
as well, so call the [`getSubErrorCodes()`](https://developers.home.google.com/reference/kotlin/com/google/home/HomeException#getSubErrorCodes()) method and check the result.

Any unhandled exceptions will result in your app crashing.

<br />

The following table provides the meanings of `HomeException` codes that you
may encounter:

| Code | Meaning |
|---|---|
| `ABORTED` | The operation was aborted, typically due to a concurrency issue such as a sequencer check failure or transaction abort. |
| `ALREADY_EXISTS` | The entity that a client attempted to create, for example a file or directory, already exists. |
| `API_NOT_CONNECTED` | The client attempted to call a method from an API that failed to connect. This can happen when the device is offline or doesn't support the API that the client attempted to call. |
| `CANCELLED` | The operation was cancelled, typically by the caller. |
| `COMMAND_FAILED` | The command failed to execute. Check the sub error codes for more details. |
| `CURSOR_WINDOW_NOT_SUPPORTED` | A method was called which uses a [`CursorWindow`](https://developer.android.com/reference/android/database/CursorWindow), but a `CursorWindow` either isn't enabled or isn't supported in the present context. |
| `DATA_LOSS` | Unrecoverable data loss or corruption has occurred. |
| `DEADLINE_EXCEEDED` | The deadline expired before the operation could complete. For operations that change the state of the system, this error may be returned even if the operation has completed successfully. |
| `DECOMMISSIONING_INELIGIBLE` | The decommissioning failed because the device isn't eligible for decommissioning. |
| `FAILED_PRECONDITION` | The operation was rejected because the system is not in a state required for the operation's execution. For example, you might get this message if the `stop` command of the `OvenCavityOperationalStateTrait` was called on an oven that's already stopped. |
| `INTERNAL` | Internal errors. This means that some invariants expected by the underlying system have been broken. This error code is reserved for serious errors. |
| `INVALID_ARGUMENT` | The client provided an argument that is outside the expected range of values. |
| `INVALID_DATA_HOLDER` | The data holder is invalid. |
| `NOT_FOUND` | A requested entity, such as a file or directory, was not found. If a request is denied for an entire class of users, such as a gradual feature rollout or undocumented allowlist, `NOT_FOUND` may be used. If a request is denied for some users within a class of users, such as user-based access control, `PERMISSION_DENIED` must be used. |
| `OUT_OF_RANGE` | The operation was attempted past the valid range, such as seeking or reading past `end-of-file`. Unlike `INVALID_ARGUMENT`, this error indicates a problem that may be fixed if the system state changes. |
| `PERMISSION_DENIED` | The caller does not have permission to execute the specified operation. `PERMISSION_DENIED` must not be used for rejections caused by exhausting some resource (use `RESOURCE_EXHAUSTED` for those errors). `PERMISSION_DENIED` must not be used if the caller cannot be identified (use `UNAUTHENTICATED` for those errors). This error code does not imply the request is valid or that the requested entity exists or satisfies other preconditions. |
| `RESOURCE_EXHAUSTED` | Some resource has been exhausted, perhaps due to a per-user quota being reached or the entire file system running out of space. For example, this error could be thrown if the `dispense` command of the `DispenseTrait` is called on a pet-feeder device but there is no more food left in the unit. |
| `SDK_INITIALIZATION_MISSING_INFO` | The SDK was initialized without all the required information. For example, this error is thrown if the client attempts to get a `TraitFactory` for a given trait ID but the trait was not included when initializing the SDK. See [Initialize the home on Android](https://developers.home.google.com/apis/initialization). |
| `UNAUTHENTICATED` | The caller cannot be identified or the request doesn't have valid authentication credentials. |
| `UNAVAILABLE` | The service is unavailable. This is most likely a transient condition, which can be corrected by retrying with a backoff. Note that it's not always safe to retry non-idempotent operations. |
| `UNIMPLEMENTED` | The requested operation isn't implemented, supported or enabled in this service. |
| `UNKNOWN` | Unknown error. `UNKNOWN` appears when an error condition occurs that can't be classified using any of the other error codes. For example, this error may be returned when a status value received from an external API lacks sufficient information as to the root cause. |
| `WRITE_FAILED` | The write failed to execute. Check the sub error codes for more details. |
[*Table: `HomeException`
codes*]

| **Note:** When inspecting logs, error codes may appear as numeric values (for example, `13` instead of `INTERNAL`). For the full list of numeric mappings, refer to the [`HomeException.Codes`
| reference](https://developers.home.google.com/reference/kotlin/com/google/home/HomeException.Codes).