How to: Handle Errors
How to: Handle Errors
How to: Handle Errors
This guide covers error handling when interacting with the C2C API. Gracefully handling HTTP errors is an essential component of a robust integration with any third-party service.
Errors in your integration can originate from various sources, which we can categorize into four main groups:
Each error category requires specific handling considerations. This guide primarily focuses on API errors, though we’ll address general strategies for the other categories as well.
Frame.io’s API communicates errors through two primary mechanisms:
HTTP status codes are standardized numerical responses that communicate the outcome of an HTTP request. For more information, see Mozilla’s HTTP status code documentation or HTTP Cats for a more visual approach.
Each Frame.io API endpoint specifies an expected success status code—typically 200 (OK), 201 (Created), or 204 (No Content). You can verify success either by checking for these specific codes or by confirming the code falls within the 200-299 range.
Status codes above 399 indicate errors. Most API errors return 4XX codes (400-499), signifying client-side issues. Errors outside this range typically originate from network infrastructure between your device and our service, with the notable exception of 500 (Internal Server Error), which indicates an unexpected issue within our server.
Similarly, a 404 (Not Found) response might be generated by intermediate services rather than our backend, despite being a 4XX code.
If you encounter unexpected status codes, please notify our team.
Frame.io returns error details in two formats: simple and detailed. Your error handling logic should accommodate both formats.
Here’s an example of a failed request with an incorrect client_secret:
Response:
The simple schema contains just a single field for error identification.
For comparison, here’s a request without proper authorization:
Response:
Detailed errors contain a message field that identifies the error type.
When handling Frame.io errors, first check for an error payload and then fall back to the HTTP status code if no payload is present.
Here’s a basic error handling implementation:
The error lookup tables referenced in this example are provided at the end of this guide.
When uploading file chunks, you interact directly with AWS S3, which has its own error format. See AWS’s common error documentation for details. As a general rule, non-fatal AWS errors should be retried at least once.
AWS errors are returned as XML:
The Code element identifies the error type.
The error tables in this guide indicate which API errors should be retried. For non-API errors from I/O operations, networking libraries, or AWS, consider retrying those that may result from transient conditions. Network congestion, temporary server outages, or packet loss typically warrant retry attempts. Most networking libraries raise TimeoutError when a request takes too long, which is a prime candidate for retry.
Computing environments can experience unpredictable issues. Even with errors that appear fatal, it’s often worth making one retry attempt. Temporary system states, hardware anomalies (such as cosmic ray bit flips), or rare memory conditions can cause seemingly fatal errors that resolve on a second attempt.
Some errors, however, should not be retried. For example, a 409: CHANNEL PAUSED response when creating an asset indicates the device is paused and should not upload. This state is deliberate and unlikely to change from a retry.
Frame.io implements rate limiting, and exceeding these limits produces either a 429: Slow Down error or a 400 status with this payload:
When you receive these responses, implement exponential backoff for retries. A recommended formula for calculating delay (in seconds) is:
Where attempt starts at 0. This produces delays of 0.5s, 1s, 2s, 4s, 8s, 16s, 32s, with all subsequent attempts waiting 32 seconds.
We recommend adding randomness (jitter) to your backoff timing to prevent request synchronization across multiple devices recovering from the same error condition. This helps mitigate the thundering herd problem where many devices retry simultaneously after an outage. A good approach is to add a random offset between 0 and half the calculated delay: math.rand(0, delay // 2).
While exponential backoff is essential for rate-limiting errors, it’s also beneficial for handling network and I/O failures generally. This approach allows temporary resource constraints to resolve without additional load from your retry attempts.
When network errors occur, they may indicate that Frame.io is unreachable because:
It’s important to detect these conditions. When an error suggests connectivity issues, implement a monitoring task that checks for service restoration and informs the user of the disconnection.
Design your application to avoid making unnecessary requests when the device is refreshing authorization, awaiting user authorization, or unable to reach Frame.io. This reduces network overhead and improves user experience.
Block all API calls (except to https://api.frame.io/health) when you detect a disconnected state. When connectivity issues arise, start a background task that polls the health endpoint and blocks further API calls until connectivity is restored.
Similarly, if token expiration occurs, block authorization-dependent calls until a new token is issued. If token refresh fails, alert the user to re-authenticate.
When polling for connection status, apply the same exponential backoff approach described earlier.
Configure appropriate timeout values for different types of requests:
Here’s a pseudocode implementation showing error handling with exponential backoff:
The following tables categorize Frame.io API errors and provide handling guidance. Here’s what each column represents:
message: The error payload message identifier
http code: The HTTP status code
error type: A conceptual error category (detailed in the descriptions section)
schema: The error payload format (simple or detailed)
retry: Retry recommendation (yes for multiple attempts, once for a single retry, no for fatal errors)
Asterisks (*) indicate special considerations detailed in the descriptions section.
See AWS’s documentation for detailed descriptions.
Both SlowDown and ServiceUnavailable from AWS indicate request rate issues and can be treated similar to Frame.io’s SlowDown error, implementing exponential backoff. Similarly, AWS’s InternalError corresponds conceptually to InternalServerError in our API.
Returned when a user declines authorization during device pairing.
Indicates a user hasn’t yet entered the device pairing code. Continue polling after the interval period specified in the device code response.
The device channel was paused when the asset was created. Do not attempt to upload this asset again.
The device pairing code has expired. Generate a new code and restart the pairing process.
Indicates an unexpected backend issue. Retry once, and please report 500 errors to our team for investigation.
Note that some known issues return 500 errors when they should return InvalidRequest:
A payload parameter contained an invalid value. Verify the parameter values match API expectations.
The request’s Content-Type header is unsupported. The API generally accepts:
form/multipart (authorization endpoints only)application/x-www-form-urlencoded (all endpoints)application/json (non-authorization endpoints)The provided credentials (client_id, client_secret, etc.) were not recognized. Verify your integration credentials.
The x-client-version header was either duplicated or contains an invalid semantic version.
The authorization grant type is invalid. Review the authorization guides for correct values.
The request parameters or payload format is incorrect. Verify field names and value formats.
If received during token refresh, your refresh token has expired and you must restart the authorization process.
You’ve exceeded request rate limits. Implement exponential backoff for subsequent requests. Note that making multiple device code requests on the same TCP connection can trigger this error—create new connections for each pairing request.
Typically indicates an expired or missing access_token. If you receive this error, refresh your token before retrying.
If encountered during token refresh, you must restart the authorization process and prompt the user to reconnect.
This error can also occur when accessing resources outside your device’s authorization scope or when a project has disabled C2C devices. Verify that you’ve requested appropriate scopes during authorization.
If this error occurs during token refresh, the entire authorization process must be restarted with user intervention.
We encourage you to contact our team with any questions and proceed to the advanced uploads guide. We look forward to supporting your integration progress.
If you haven’t already, please review the Implementing C2C: Setting Up guide before proceeding.
You’ll need the access_token obtained during the authentication and authorization process.
This guide builds on the Basic Upload guide and Advanced Uploads guide.