go: net/http: "missing status pseudo header" when reusing HTTP/2 connection

What version of Go are you using (go version)?

1.9.2

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

GOHOSTARCH="amd64"
GOHOSTOS="darwin"

What did you do?

Reusing an HTTP client resulted in a panic, example code: https://play.golang.org/p/DGUqwSMygZ Unfortunately, I was unable to reproduce this issue again, still find it worth reporting it here.

Panic trace:

Got response!
failed to GET: missing status pseudo header
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x11d5340]

goroutine 7 [running]:
net/http.(*http2pipe).Write(0xc420457ce8, 0xc4200620e0, 0x51, 0x64, 0x0, 0x0, 0x0)
	/usr/local/Cellar/go/1.9.2/libexec/src/net/http/h2_bundle.go:3661 +0x100
net/http.(*http2clientConnReadLoop).processData(0xc420489fb0, 0xc42007f560, 0xc42007f560, 0x0)
	/usr/local/Cellar/go/1.9.2/libexec/src/net/http/h2_bundle.go:8259 +0x2ac
net/http.(*http2clientConnReadLoop).run(0xc420489fb0, 0x12a9300, 0xc4200357b0)
	/usr/local/Cellar/go/1.9.2/libexec/src/net/http/h2_bundle.go:7896 +0x54f
net/http.(*http2ClientConn).readLoop(0xc420080820)
	/usr/local/Cellar/go/1.9.2/libexec/src/net/http/h2_bundle.go:7788 +0x9d
created by net/http.(*http2Transport).newClientConn
	/usr/local/Cellar/go/1.9.2/libexec/src/net/http/h2_bundle.go:7053 +0x6b9
exit status 2

The first request succeeded, (Got response!), the second one failed (failed to GET: missing status pseudo header) and most likely the third one caused the panic. Is this a bug? Do Go HTTP clients need to be reinstantiated upon request failure?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 20 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Thanks for confirming. I’ll fix the http2 server and make sure we’re consistent in behavior from Go’s API point of view between http1 and http2.

hi @bradfitz. it’s a net/http go server, actually. we’re binding to ":443" directly using https://godoc.org/net/http#Server.ListenAndServeTLS to get the HTTP/2 features.

the binary on production was built with:

go version go1.9 linux/amd64

GOOS="linux"
GOARCH="amd64"

@bradfitz you’re right, there was a case where we were failing to overwrite a default zero-value and passing that into WriteHeader. that branch of logic only happened in a timeout case (during moments of very high traffic), so that’s why it was only happening occasionally from @leonklingele’s perspective. I’ve deployed to production an update which fixes this.