Description
What version of Go are you using (go version
)?
Go 1.17.3
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
linux/amd64
What did you do?
- Use an
http.Client
with (any)Timeout
set - Make an HTTP/2 request
- Read the body
- Close the body
Demo code:
package main
import (
"io"
"log"
"net/http"
"time"
)
func main() {
client := &http.Client{Timeout: time.Minute}
for i := 0; i < 20; i++ {
resp, err := client.Get("https://google.com")
if err != nil {
log.Fatal(err)
}
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
log.Fatal(err)
}
if err := resp.Body.Close(); err != nil {
log.Fatalf("[i=%d] body close error: %s", i, err)
}
}
}
(I'm pinging google.com as an easy way to get an HTTP/2 request going.)
What did you expect to see?
No error, at least not on the resp.Body.Close()
call.
What did you see instead?
For example:
2021/11/04 15:49:08 [i=0] body close error: context canceled
Sometimes it takes a few iterations to hit an error.
This is HTTP/2-specific: with GODEBUG=http2client=0
it does not reproduce.
This does not occur in Go 1.17.2 but it started happening with 1.17.3.
I realize it's weird to be checking the resp.Body.Close
error in the first place. This came up in the context of twirp; I'm going to send a PR to them to stop checking the error. Even so, I don't think we should get this error in the client. It's especially confusing because we get the error immediately (so it's not related to the 1 minute timeout specifically).
I bisected on master to 7109323, which is CL 353870. The original x/net/http2 CL is CL 353390 and it was backported for Go 1.17.3 as CL 357683.