Learn through the super-clean Baeldung Pro experience:
>> Membership and Baeldung Pro.
No ads, dark-mode and 6 months free of IntelliJ Idea Ultimate to start with.
Last updated: July 24, 2024
We’ve all probably encountered an HTTP error and wondered if we should hit that retry button.
In this tutorial, we’ll discuss which HTTP error status codes are a no-go for retries, why, and which ones might need a bit of patience.
An HTTP status code is a three-digit number that provides information on the state of our request:
| HTTP status code | Type of error | Meaning | Explanation |
|---|---|---|---|
| 1xx | Informational | Received | The request has been received and is being processed; this code is rarely seen |
| 2xx | Success | All Good! | Everything went smoothly, and our request was successful |
| 3xx | Redirection | Hold On | We need to take additional steps to complete the request |
| 4xx | Client Errors | Client issue | The client’s actions are the reason for the issue, and the server is operating normally |
| 5xx | Server Errors | Server issue | Something went wrong on the server |
The 3xx, 4xx, and 5xx codes indicate errors on the client or server sides. Knowing how to interpret the received error code lets us determine what went wrong and what to do.
Retrying common 3xx codes requires that we understand and adhere to the given redirect instructions.
The following table shows why common 3xx status codes are a no-go for retries:
| Redirection Code | Meaning | Explanation | Why not Retry? |
|---|---|---|---|
| 301 | Moved Permanently | The requested resource has been permanently moved to a new URL | Need to update the request to use the new URL. Retrying with the old URL will result in the same response |
| 302 | Temporary Redirect | The resource is temporarily available at a different URL | Need to update the request to use the new UR |
| 303 | See Other | The response can be found under a different URL and can be accessed with a GET request | No point in retrying without access to the given URL |
| 304 | Not Modified | The resource has not changed since the last request | Suitable for caching purposes, so retrying doesn’t make sense |
| 307 | Temporary Redirect | Similar to 302, but the request method should not be changed when retrying the new location | Need to follow the redirect to the new URL before trying again |
| 308 | Permanent Redirect | Similar to 301, but the request method must not be changed | Need to follow the redirect to the new URL before trying again |
The goal is to adapt to the new URL or resource location that the server has supplied, not to try the same request again.
The following table shows why common client-side status codes are a no-go for retries:
| Client-Side Error Code | Meaning | Explanation | Why not Retry? |
|---|---|---|---|
| 400 | Bad Request | The server didn’t understand our request | Something went wrong with what we sent over |
| 401 | Unauthorized | Incorrect login credentials | No point in retrying without proper authentication |
| 403 | Forbidden | We’re not allowed to access this resource | No point in retrying without access rights |
| 404 | Not Found | What we’re looking for isn’t here | If it’s not there, no amount of retries will change that |
| 405 | Method Not Allowed | The method we’re using isn’t allowed | Need to adjust our request method before trying again |
| 406 | Not Acceptable | Response headers of the client request are incompatible with the server | Before retrying, we need to correct the response headers of our request |
| 410 | Gone | The requested resource has been permanently removed | It’s permanently gone |
There are other 4xx status codes, but these are the most common
Not every client-side error is a no-go for retries. For example, the request timeout (408 ) can happen because of a network problem. So, it makes sense to wait and try again later. Similarly, the too-many-requests code (429) is a sign of rate restriction, so we can try the request again when the rate limit window has been reset.
Each 5xx error code represents a distinct problem that can occur on the server’s end.
The following table shows why common server-side status codes are a no-go for retries:
| Server-Side Error Code | Meaning | Explanation | Why not Retry? |
|---|---|---|---|
| 500 | Internal Server Error | The server had a bit of an issue | Sometimes, retries might help, but often, the issue needs fixing on the server side first. |
| 501 | Not Implemented | The server doesn’t support the functionality | Not going to work without server changes |
| 502 | Bad Gateway | A server upstream got confused | It might be worth a retry later, but it often requires fixing the underlying issue |
| 503 | Service Unavailable | The server is overloaded or down for maintenance | The server is overloaded or down for maintenance |
| 505 | HTTP Version Not Supported | The server doesn’t support the HTTP protocol version used in the request | Need the modified request with the supported HTTP version |
| 507 | Insufficient Storage | The server can’t save the representation required to finish the request | Need a change in the server’s storage capacity, which isn’t something a client can do |
| 511 | Network Authentication Required | The client needs to authenticate to gain network access | There’s no point in resending the request without prior identity verification |
These are the most common 5xx codes for which retries don’t make sense.
Not all server codes are a no-go for retries. For example, it’s usually okay to attempt again after a 504 error (Gateway Timeout), as it’s typically caused by a sluggish server response.
The HTTP status codes 506 (Variant Also Negotiates) and 508 (Loop Detected) are both associated with loops in server responses.
The server returns a 506 status code when it finds a loop in the negotiating process, while the 508 status code indicates that the entire operation failed because it encountered an infinite loop while processing a request.
Retries aren’t recommended for both 506 and 508 unless the server configuration is fixed to stop similar loops from occurring.
Adhering to established practices can save us from trouble when dealing with HTTP failures and determining when to try again.
As we’ve seen, some error codes represent the issues that won’t be resolved by trying again.
We can use exponential backoff for retries for the codes for which it makes sense to retry requests. This means gradually increasing the waiting time between successive attempts to prevent server-side overcrowding.
For example, let’s say that the HTTP request times out, and the server sends the status 500 (Internal Server Error).
At this point, the retry process can begin. However, before retrying, the client waits for a short period, such as one second.
When the first attempt fails, the client waits for a longer delay, such as two seconds, before sending the request again. If the second attempt fails, the client waits four seconds more before attempting again.
Due to the exponential backoff mechanism, the delay time doubles with every retry. To avoid infinite retrying, we set the maximum number of retries. If none are successful, the user is alerted.
To optimize user experience, apps should implement graceful degradation and fallback methods. The goal is to enable the client to function even if the server is briefly unavailable. For instance, this can be achieved by having the client use cached data instead of the server’s live data when the server is unreachable.
Circuit breakers and proper timeouts can also prevent clients’ requests from lingering forever. This avoids delays and repeated attempts to access a faulty service. The most important thing is to receive a clear and actionable response from the server.
Finally, when getting an HTTP error code 503, the Retry-After header tells us how long to wait before retrying. This method guarantees effective issue resolution and improves overall user experience.
In this article, we explored which HTTP status codes are a no-go for retries and why.
They occur because something is wrong with the client request or the server, so a retry doesn’t make sense before fixing the request or the server.