air-verse/air · error
proxy inject: failed to init gzip reader: %w
Error message
proxy inject: failed to init gzip reader: %w
What it means
When proxying, injectLiveReload detects a gzip Content-Encoding header and wraps resp.Body in gzip.NewReader to read the decompressed HTML before injecting the reload script. If the gzip stream is corrupt or empty, this error is returned.
Source
Thrown at runner/proxy.go:125
}
func (p *Proxy) Reload() {
p.stream.Reload()
}
func (p *Proxy) BuildFailed(msg BuildFailedMsg) {
p.stream.BuildFailed(msg)
}
func (p *Proxy) injectLiveReload(resp *http.Response) (string, bool, error) {
var reader io.Reader = resp.Body
decoded := false
switch detectContentEncoding(resp.Header) {
case encodingGzip:
gzipReader, err := gzip.NewReader(resp.Body)
if err != nil {
return "", false, fmt.Errorf("proxy inject: failed to init gzip reader: %w", err)
}
defer gzipReader.Close()
reader = gzipReader
decoded = true
case encodingBrotli:
reader = brotli.NewReader(resp.Body)
decoded = true
}
buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(reader); err != nil {
return "", decoded, fmt.Errorf("proxy inject: failed to read body from http response: %w", err)
}
page := buf.String()
// the script will be injected before the end of the body tag. In case the tag is missing, the injection will be skipped with no error.
body := strings.LastIndex(page, "</body>")
if body == -1 {View on GitHub (pinned to 71ea1dee05)
Solutions
- Fix the upstream app so it only sets Content-Encoding: gzip when it actually compresses the body
- Disable compression in the upstream app/middleware so air receives plain responses
- Check the wrapped %w error: gzip.ErrHeader / unexpected EOF indicate corrupt or truncated streams
- Bypass other compression layers (CDN/ingress) between air's proxy and the app
Example fix
// before (upstream app)
w.Header().Set("Content-Encoding", "gzip")
w.Write([]byte(html)) // not actually gzipped
// after
w.Write([]byte(html)) // let the framework compress or drop the header Defensive patterns
Strategy: try-catch
Validate before calling
// verify upstream doesn't lie about gzip
resp, _ := http.Get("http://localhost:" + appPort + "/")
if resp.Header.Get("Content-Encoding") == "gzip" {
zr, err := gzip.NewReader(resp.Body)
if err != nil {
log.Printf("upstream sends invalid gzip: %v", err)
}
_ = zr
} Try / catch
if err := startProxy(); err != nil && strings.Contains(err.Error(), "failed to init gzip reader") {
// disable compression upstream, then retry
} Prevention
- Only set Content-Encoding: gzip when actually compressing
- Prefer framework-managed compression (middleware) over manual headers
- Test the app directly (curl --compressed) before proxying through air
- Keep dev-mode compression off for simpler proxying
When it happens
Trigger: The upstream app responds with Content-Encoding: gzip but the body is not valid gzip data — e.g. the app sets the header manually but sends uncompressed bytes, or the stream is truncated.
Common situations: Backend frameworks double-encoding or lying about the encoding header; middleware setting Content-Encoding: gzip without actually compressing; proxying non-Golang servers with broken compression middleware.
Related errors
- proxy inject: failed to read body from http response: %w
- proxy handler: bad form
- proxy handler: unable to create request
AI-assisted analysis of air-verse/air@71ea1dee05 (2026-08-31).
Data as JSON: /api/errors/34f9230641cabcc2.
Report an issue: GitHub.