Skip to main content

API Call Recovery: Handling Failed Requests Gracefully

Last updated on February 27, 2025

If a game tries to send an API request multiple times but still can’t receive the success response when losing a connection to the backend service, it’s important to have a proper error handling. Without one, certain features—like saving progress, updating friend lists, or matchmaking—might stop working properly, leading to a frustrating experience for players.

To avoid this, consider adding fallback mechanisms to handle failed API calls gracefully. This could mean temporarily storing data locally until the connection is restored or showing a friendly message to let players know what’s happening. These small details can make a big difference in keeping the game experience smooth and enjoyable, even when network issues occur.

When using an API function, it's important to handle situations where the request fails. If a request doesn’t go through, the game should respond in a way that prevents errors or a bad player experience.

HTTP Error Codes

The API retry system will automatically attempt a retry when it encounters any of the following HTTP error codes:

  • 429 (Too Many Requests) – The server is getting too many requests at once.
  • 449 (Retry With) – The request needs to be retried with different conditions.
  • 500 (Server Error) – Something went wrong on the server.
  • 502 (Bad Gateway) – The server got an invalid response from another service.
  • 503 (Service Unavailable) – The server is temporarily unavailable.
  • 504 (Gateway Timeout) – The server took too long to respond.

HTTP Retry Mechanism

The HTTP retry settings are defined in the Unreal Engine SDK inside AccelByteHttpRetryScheduler.cpp, while the logic for calculating the next retry attempt is handled in FHttpRetryTask::ScheduleNextRetry() inside file AccelByteHttpRetryTask.cpp.

int FHttpRetryScheduler::InitialDelay = 1; // Initial delay for the next retry attemps in seconds.
int FHttpRetryScheduler::MaximumDelay = 30; // Maximum delay for the next retry attemps in seconds.
int FHttpRetryScheduler::TotalTimeout = 60; // Total retry timeout in seconds.

Here's how the retry timing works:

  1. The first retry starts with an initial delay (default is 1 second).
  2. Each retry delay doubles compared to the previous one.
  3. A small random variation is added by taking a value between -next delay and +next delay, dividing it by four, and applying it to the delay. This prevents retries from happening at perfectly predictable intervals.
  4. The delay will never exceed the maximum limit (default is 30 seconds). If it goes beyond this, it is capped at the maximum delay.
  5. If the total time spent on retries exceeds the total timeout (default is 60 seconds), the system stops retrying and returns an error code ErrorCodes::NetworkError (14005).

This retry mechanism helps balance quick error recovery with avoiding excessive requests when the server is having issues.

The retry mechanism was implemented by default and released on:

  • Unreal Engine AGS SDK 9.0.0
  • Unreal Engine AGS OSS 0.1.0
danger

The HTTP retry settings are designed to handle temporary network issues automatically and shouldn’t be changed. If a request keeps failing for more than X seconds, it usually means there’s a serious network problem. In this case, instead of increasing the timeout (which would just make players wait longer with no guarantee of success), it’s better to handle the failure gracefully—like returning the player to the main menu or showing a connection error message. This way, players aren’t stuck waiting and can try again later.

Handling HTTP Retry Time Out

Currently, in the Unreal Engine project, handling the HTTP retry timeout is only possible if the game directly integrates the AGS Unreal Engine SDK. If the game uses the AGS OSS SDK instead, it won’t have control over the HTTP retry behavior. The OSS SDK simply reports whether an API request was successful or not. If it fails, the error messages are usually generic, such as block-player-request-failed, unblock-player-request-failed, or send-ds-ready-request-failed.

If the HTTP API retry is timed out, the ErrorCode value of the FErrorHandler delegate of the API response will value ErrorCodes::NetworkError (14005). For example, when implementing Search for Players, the HTTP retry timeout can be identified by checking the ErrorCode value of FErrorHandler delegate:

...
FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
FString Query = FString("UsersDisplayName");
EAccelByteSearchType By = EAccelByteSearchType::DISPLAYNAME;

ApiClient->User.SearchUsers(Query,
By,
THandler<FPagedPublicUsersInfo>::CreateLambda([](const FPagedPublicUsersInfo & Result)
{
// Do something if SearchUsers succeeds

}), FErrorHandler::CreateLambda([](int32 ErrorCode, const FString & ErrorMessage) {
// Do something if SearchUsers fails
UE_LOG(LogTemp, Warning, TEXT("Error SearchUsers. Code: %d, Message: %s"), ErrorCode, *ErrorMessage);

if(ErrorCode == static_cast<int32>(ErrorCodes::NetworkError))
{
// Implement a solution to handle HTTP retry timeout.
}
})
);
...

If the request encounters one of the error codes listed here, the error delegate will not be triggered when the system starts to retry the request. The error delegate will only be triggered after the retry process ends—either when the retry limit is reached (timeout) or if the final response code is not one of the listed error codes.

Example HTTP Error Handling in the Bytewars UI Implementation

Properly handling API call failures improves the player experience. In each Byte Wars learning module, we manage API failures by showing an error message in the game’s UI. However, as mentioned above, since Byte Wars uses the AGS OSS SDK, it cannot identify HTTP retry timeouts error. This is because the HTTP retry timeout can only be detected when using the Unreal Engine SDK directly, without the AGS OSS SDK. As a result, the error messages in Byte Wars are often generic, meaning the game cannot determine if the failure was due to an HTTP retry timeout or another issue.

You’ll find examples of how to handle failed requests correctly. These examples show how to display helpful messages to players.