# Sad paths and errors Using APIs to read and control real-world devices is complex, and unexpected situations will inevitably occur in the physical world that your application should be prepared for. Below are common exceptions to the typical happy path and best practices on how your application should handle them. Prepare for errors: Systematic, programmatic handling of sad paths in your UX leads to less confusion for users and builds confidence and trust in your application’s overall functionality. ### Missing device capability Example scenario: A vehicle can’t broadcast its GPS location, preventing smart charging from knowing where the vehicle is. - Handling [interventions](https://developers.enode.com/docs/interventions) for all the brands and capabilities you intend to support is critical for gracefully handling real-world issues that arise. Occasionally refer back to our documentation for the latest known interventions. - Always check each device’s `capabilities` hash in the API to understand that specific unit’s capabilities. Even if a specific _brand/model_ should support a capability, there are situations where a specific _device_ will not! ### Deauthorized vendors and credentials refreshing Example scenario: The Enode connection is deauthorized due to an external event, like a credentials change, or a token invalidation. A common reason is that the user has reset the password on their vendor app. - The connection to Enode may become invalid due to external events. In these scenarios, the user will need to relink their account to your app via Enode. - The connection to Enode becomes invalid, information about devices for that vendor will no longer be returned via the API and you will stop receiving updates about those devices. Relinking the same account will result in the data repopulating via the API with the same IDs as before. - Listen to the [`user:credentials:invalidated` webhook](https://developers.enode.com/docs/webhooks#user-credentials-invalidated) to learn about every time this happens. ### Deleted devices Example scenario: Your user removes one of four thermostats from their Ecobee account. - Your users may disassociate a device from their vendor account. Device data is permanently deleted from Enode when this happens. - Listen to `user:{vendorType}:deleted` [webhooks](https://developers.enode.com/docs/webhooks) to learn about every time this happens. - If the same real-world device is added back to a user’s vendor account, Enode will send a new `user:{vendorType}:discovered` webhook. Unlike with deauthorized vendors, historical data for the device will not be available and the device will have a new ID. ### Action preconditions not met Example scenario: Your app asks a thermostat to follow device schedule, but it’s already following device schedule. - Be sure to handle scenarios where [actions](https://developers.enode.com/docs/integration-guide/controlling-devices#actions) are immediately created in the `CANCELLED` state. Actions such as [Control Charging](https://developers.enode.com/api/reference#postVehiclesVehicleidCharging) can be created in the `CANCELLED` state if we know that the action cannot be done. ### Action failures Example scenario: A charge command is not accepted by a vehicle before timing out. - Actions may time out and fail after you create them. When you notice that an action has transitioned to `FAILED`, notify your users or begin a retry/recovery process. - For vehicle charging actions, you can reference `failureReason` to understand why the charge action failed. The `powerDeliveryState` field can also provide additional details about whether a charger is functioning. ### Outdated device data Example scenario: The vendor cloud returns the best information it has about a vehicle, but the vendor hasn’t received information in over a day because the vehicle is underground and cannot connect to the network. - Device connectivity, vendor cloud disruptions, and other issues often impact individual device freshness. Your application should have a built-in tolerance for data that may fall outside our typical [freshness guidance](https://developers.enode.com/docs/integration-guide/device-data). - When available, rely on [`lastUpdated` fields](https://developers.enode.com/docs/integration-guide/device-data) to determine the freshness of data itself. Use `isReachable` and `lastSeen` to determine connectivity with the vendor cloud and device. - Refer to the [Enode Status](https://status.enode.io/) page to see if there are systemic issues affecting specific vendors. ### Unexpected smart charging behavior Example scenario: Charging occurred outside the planned time for smart charging. - There are many factors at play that can affect how smart charging works in practice. To reduce confusion, be sure to educate your users on some of the most common issues such as: - Not having any other 1st or 3rd party apps or schedules control charging - Smart charging will only work when energy savings is sufficient - A vehicle may begin charging immediately when plugged in when a smart charging plan is in the `CONSIDERING` state - Be sure to listen to the [`PLAN` events](https://developers.enode.com/docs/smart-charging/states-of-smart-charging#plan) for the best information on why smart charging is behaving a certain way. - Refer to our detailed [smart charging guide](https://developers.enode.com/docs/smart-charging/states-of-smart-charging) for more information. ## Best practices for error handling Your integration should include robust error handling to provide the best user experience possible and minimize frustration when things go wrong. Refer to our [API Reference](https://developers.enode.com/api/reference#errors-and-problems) for a detailed list of error codes. When handling errors, follow these best practices: - Consider implementing a hierarchy of error handling: - Build explicit handling for sad paths you know and care about. Treat these as first-class product features with polished designs and recovery paths - Unexpected vendor issues should be communicated as such as not to question the reliability of your own application. Prompt the user to try again later - For all other errors, use generic error messaging - Keeping a log of state changes for a device or action to enable easier debugging and allows Enode to better support you diagnosing potential issues