Context Deadline Exceeded
is an error occurring in Go when a context of an HTTP request has a deadline or a timeout set, i.e., the time after which the request should abort. This error is returned if the time of a server response is greater than the set timeout. Setting timeouts on requests is a good practice in a production environment to ensure that you always get a response (or error) in a finite time.
Context deadline exceeded
example
package main
import (
"context"
"errors"
"log"
"net/http"
"os"
"time"
)
func slowServer(w http.ResponseWriter, r *http.Request) {
time.Sleep(10 * time.Second)
w.Write([]byte("Hello world!"))
}
func call() error {
client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, "http://localhost:8080", nil)
if err != nil {
return err
}
ctx, cancel := context.WithTimeout(req.Context(), 1*time.Second)
defer cancel()
req = req.WithContext(ctx)
_, err = client.Do(req)
return err
}
func main() {
// run slow server
go func() {
http.HandleFunc("/", slowServer)
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}()
time.Sleep(1 * time.Second) // wait for server to run
// call server
err := call()
if errors.Is(err, context.DeadlineExceeded) {
log.Println("ContextDeadlineExceeded: true")
}
if os.IsTimeout(err) {
log.Println("IsTimeoutError: true")
}
if err != nil {
log.Fatal(err)
}
}
Output:
2021/08/19 06:39:09 ContextDeadlineExceeded: true
2021/08/19 06:39:09 IsTimeoutError: true
2021/08/19 06:39:09 Get "http://localhost:8080": context deadline exceeded
exit status 1
In the example above, we:
- run our slow server, whose task is to return a response after 10 seconds
- create a new request in the
call()
function, which will be sent to the server - set a timeout of 1 second on this request, i.e., the value of time after the waiting for the server response is interrupted
- send the request to the server
Since a timeout for this request is set to 1 second and the server responds after 10 seconds, the HTTP client returns an error.
Handle Context deadline exceeded
error
An HTTP client returns the context.DeadlineExceeded
error when the set timeout is exceeded. This error can also be handled with the more general os.IsTimeout()
function that checks if the error is known to report that a timeout occurred.
Context deadline exceeded (Client.Timeout exceeded while awaiting headers)
example
The timeout can be set not only at the level of a single HTTP request but also at the level of the entire HTTP client. In this case, each request made by such a client has the same timeout value. See the example of a call()
function using the client timeout option:
func call() error {
client := &http.Client{Timeout: 1 * time.Second}
_, err := client.Get("http://localhost:8080")
return err
}
Output:
2021/08/19 07:35:14 IsTimeoutError: true
2021/08/19 07:35:14 Get "http://localhost:8080": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
exit status 1
In this case, we get the context deadline exceeded (Client.Timeout exceeded while awaiting headers)
error. Note that this is not an instance of context.DeadlineExceeded
error.