# Error Handling
This guide covers features in the Facebook SDK for iOS which help respond to errors returned by Facebook.
## General Best Practices {#best_prac}
Each framework in the SDK defines the errors in the `FBSDK*Constants.h` file. The Facebook SDK populates keys defined in `FBSDKConstants.h` in `FBSDKCoreKit.framework` in the `userInfo` dictionary of `NSErrors` where possible.
You should display only the localized messages as errors. One exception is Graph API requests that utilize the automatic error recovery described below.
## Error Handling and Recovery {#errorhandling}
Error objects include:
- `NSError` - The SDK returns these objects for request callbacks and they are easier to interpret
- `NSErrorRecoveryAttempting` - The SDK provides data in `NSError` which is easier to extract and conforms to the informal protocol `NSErrorRecoveryAttempting`
NSError objects have `userInfo` dictionaries that contain the following keys:
| Error | Description |
| --- | --- |
| `FBSDKErrorDeveloperMessageKey` | An error message for the developer |
| `FBSDKErrorLocalizedDescriptionKey` | A localized user facing message, if available |
| `FBSDKErrorLocalizedTitleKey` | A localized user facing title, if available |
| `FBSDKGraphRequestErrorCategoryKey` | An enum describing if the error category, such as transient, recoverable, other |
| `FBSDKGraphRequestErrorGraphErrorCode` | The Graph API error code |
| `FBSDKGraphRequestErrorErrorSubcode` | The Graph API error subcode |
| `FBSDKGraphRequestErrorHTTPStatusCodeKey` | The HTTP status code returned by the Graph API |
| `FBSDKGraphRequestErrorParsedJSONResponseKey` | The raw JSON response from the Graph API |
`NSError` instances may also contain data conforming to the informal protocol `NSErrorRecoveryAttempting`. If the category `(FBSDKGraphRequestErrorCategoryKey)` is transient or recoverable, the error `userInfo` contains:
| Error | Description |
| --- | --- |
| `NSRecoveryAttempterErrorKey` | A recovery attempter conforming to `<FBSDKErrorRecoveryAttempting>` that conforms to informal protocol `<NSErrorRecoveryAttempting>` |
| `NSLocalizedRecoverySuggestionErrorKey` | A localized user facing message describing the recovery |
| `NSLocalizedRecoveryOptionsErrorKey` | An array of localized labels for buttons describing the recovery options |
## Login Error Handling {#renew}
Errors rarely occur in the typical login flow because the login dialog presented by Facebook via single sign on guides the users to resolve any errors. There are two exceptions you need to consider:
- If you specified a login behavior of `FBSDKLoginBehaviorSystemAccount`
- Handling declined permissions
__`FBSDKLoginBehaviorSystemAccount`__
In the case of `FBSDKLoginBehaviorSystemAccount`, the UI is provided by iOS natively. As a result, there can be errors that require user action to resolve such as if they changed their password on [www.facebook.com](http://www.facebook.com/) or their account has been disabled for security reasons.
In those cases the login API will provide an appropriately coded `NSError` instance (with the above localized keys) that you can display. Note `FBSDKLoginBehaviorSystemAccount` is not the default login behavior, and the other login behaviors will provide appropriate messaging in the login dialog automatically.
__Handling Declined Permissions__
This is technically not an error condition as no `NSError` instance is returned, but an important scenario to consider nonetheless. `FBSDKAccessToken` provides a `declinedPermissions` property which describes all the permissions the user has declined for your application over their lifetime. This includes any declines on other devices.
More convenient is the `declinedPermissions` property on `FBDKLoginResult` which is returned to the `FBSDKLoginManager` callback or `FBSDKLoginButton` delegate. The `FBSDKLoginResult.declinedPermissions` reflects the declined permissions in the associated request and is a good place to check if the user has declined some of the permissions you requested.
If the user declines permissions, you should not immediately ask for the permissions again. Instead your app should continue functioning. You may consider providing a guide or user interface explaining the benefits of granting that permission but should only ask for it again if the user performs an action that needs it.
## Handling Graph API Errors {#api}
You may encounter different kinds of errors when working with the Graph API such as:
- Request throttling on Facebook's servers
- Missing parameters
- Insufficient permissions
More importantly, users might have taken actions outside of your app that would change the access token's authorization and result in a Graph API error
- Removing your app from App Settings on Facebook
- De-authorizing permissions for your app
- Changing their Facebook password
To help with these scenarios, the Facebook SDK populates additional keys in the `NSError userInfo`:
| Error | Description |
| --- | --- |
| `FBSDKGraphRequestErrorCategoryKey` | An enum describing if the error category. Includes transient, recoverable, other. |
| `FBSDKGraphRequestErrorErrorCode` | The Graph API error code. |
| `FBSDKGraphRequestErrorErrorSubcode` | The Graph API error subcode. |
| `FBSDKGraphRequestErrorHTTPStatusCodeKey` | The HTTP status code returned by the Graph API. |
| `FBSDKGraphRequestErrorParsedJSONResponseKey` | The raw JSON response from the Graph API. |
So for example, to check if the error was permissions related, you can inspect the code value to see if it is equal to 200. See [Using Graph API, Handling Errors](https://developers.facebook.com/docs/graph-api/using-graph-api#errors).
#### Error Recovery {#graph_recover}
`NSError` instances may also contain data conforming to the informal protocol `NSErrorRecoveryAttempting`. Specifically, if the category `(FBSDKGraphRequestErrorCategoryKey)` is transient or recoverable, the
error `userInfo` contains:
| Error | Description |
| --- | --- |
| `NSRecoveryAttempterErrorKey` | A recovery attempter conforming to `<FBSDKErrorRecoveryAttempting>` which conforms to informal protocol `<NSErrorRecoveryAttempting>` |
| `NSLocalizedRecoverySuggestionErrorKey` | A localized user facing message describing the recovery. |
| `NSLocalizedRecoveryOptionsErrorKey` | An array of localized labels for buttons describing the recovery options. |
This allows you to easily extract the recovery attempter and ask it to attempt to recover from the error, which may prompt UI for the user. For example, if the token is expired the recovery attempter will ask the user if they want to log in again. The attempter will notify its delegate upon recovery success or failure. See Apple's documentation on [Error Recovery](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ErrorHandlingCocoa/ErrorRespondRecover/ErrorRespondRecover.html#//apple_ref/doc/uid/TP40001806-CH203-BAJJHBED).
To make it simpler to subscribe to best practices, the SDK provides `FBSDKGraphErrorRecoveryProcessor` which can process errors for you, such as presenting alerts or dialogs automatically. See its reference docs for details.
More importantly, non-batched `FBSDKGraphRequests` will automatically use `FBSDKGraphErrorRecoveryProcessor` so that transient errors and recoverable errors that succeed are automatically retried (once). You can disable this by setting `-[FBSDKGraphRequest setGraphErrorRecoveryDisabled:YES]` (or disable globally in `FBSDKSettings`)
## Sharing Errors {#sharing}
The ShareKit APIs follow the above information with regards to the data in `NSError userInfo` dictionaries and may wrap the errors so you should consider inspecting the `NSUnderlyingError` key. Additionally, the `FBSDKShareAPI` uses `FBSDKGraphRequests` internally which follows the error recovery behavior outlined above. If that is not desired, you should disable the error recovery globally via `[FBSDKSettings setGraphErrorRecoveryDisabled:YES]`.
## Learn More
* [Graph API, Handling Errors](https://developers.facebook.com/docs/graph-api/using-graph-api#errors)
* [Test a Login Flow](https://developers.facebook.com/documentation/facebook-login/guides/test)
* [Errors and Exceptions at developer.apple.com](https://developer.apple.com/documentation/foundation/errors_and_exceptions)