golang/go · error · module.VersionError
downloaded zip file too large
Error message
downloaded zip file too large
What it means
This error is thrown when a module zip file downloaded from a Go module proxy exceeds the maximum allowed size of 500 MiB (codehost.MaxZipFile = 500 << 20). The proxy client wraps the response body in an io.LimitedReader with a budget of MaxZipFile+1 bytes. If the remaining budget (lr.N) drops to zero or below after io.Copy, the download consumed the full budget, meaning the zip is at or beyond the size ceiling.
Solutions
- Check if the module genuinely needs to ship 500+ MiB of content; split it into smaller sub-modules or move large assets to a release/download artifact outside the Go module zip.
- Use a different version of the module that is smaller (e.g., go get example.com/mymodule@v1.2.0 instead of a bloated release).
- If the module is your own, restructure: move large files out of the module, use //go:embed with externally fetched assets, or use Go toolchain modules more carefully.
- Set GOPROXY=direct and use GOFLAGS=-mod=mod if the issue is a proxy serving corrupt data, but note the size limit is enforced in the client regardless of proxy.
- Report the issue to the module author — the 500 MiB limit is a hard client-side ceiling and cannot be raised via configuration.
Example fix
// before: module ships 600MB of model weights in /assets // module structure: mymodule/assets/weights.bin (500MB+) // after: fetch weights separately at runtime or build time // go.mod stays small; weights downloaded via a Makefile target package mymodule //go:embed config.json var configBytes []byte // small file only // large files fetched separately: // $ make download-weights
Defensive patterns
Strategy: validation
Validate before calling
// Check module size before downloading (if proxy provides Content-Length)
// Shell: curl -sI "https://proxy.golang.org/<module>/@v/<version>.zip" | grep -i content-length
// Go wrapper:
func checkModuleSize(proxyURL, modPath, version string) error {
url := fmt.Sprintf("%s/%s/@v/%s.zip", proxyURL, modPath, version)
resp, err := http.Head(url)
if err != nil { return err }
defer resp.Body.Close()
if resp.ContentLength > 500*1024*1024 {
return fmt.Errorf("module zip is %d bytes, exceeds 500 MiB limit", resp.ContentLength)
}
return nil
} Try / catch
// Parse go command stderr for this specific error
if strings.Contains(stderr, "downloaded zip file too large") {
// Module exceeds hard limit; cannot be worked around via config
// Recommend splitting the module or using an older/smaller version
} Prevention
- Audit module sizes before adding large dependencies
- Use 'go mod download -json' in CI to catch size issues early
- Monitor module size changes during go get -u upgrades
- Consider vendoring large modules to detect size issues at commit time
When it happens
Trigger: Triggered by GOPROXY-based module downloads (e.g., go mod download, go get, go mod tidy) when the .zip artifact served by the proxy is larger than 500 MiB. The proxy.ReadZip/Zip path streams the body through the LimitedReader and checks lr.N afterwards.
Common situations: A module with very large bundled assets (e.g., embedded binaries, ML model weights, large test fixtures) is published to a Go proxy and exceeds the 500 MiB ceiling. A malicious or misconfigured proxy serves an oversized or infinitely-streaming response. A corrupted proxy or CDN returns an error page that happens to be large. Rare but real for modules like terraform-provider packages or modules shipping prebuilt binaries.
Related errors
- loading deprecation for
- lookup
- reading / at revision
- ambiguous semantic version
- can't decode XML document using charset
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/06b5331273c01d38.
Report an issue: GitHub.
Appendix: source
Thrown at src/cmd/go/internal/modfetch/proxy.go:446
if err != nil {
return p.versionError(version, err)
}
path := "@v/" + encVer + ".zip"
body, redactedURL, err := p.getBody(ctx, path)
if err != nil {
return p.versionError(version, err)
}
defer body.Close()
lr := &io.LimitedReader{R: body, N: codehost.MaxZipFile + 1}
if _, err := io.Copy(dst, lr); err != nil {
// net/http doesn't add context to Body read errors, so add it here.
// (See https://go.dev/issue/52727.)
err = &url.Error{Op: "read", URL: redactedURL, Err: err}
return p.versionError(version, err)
}
if lr.N <= 0 {
return p.versionError(version, fmt.Errorf("downloaded zip file too large"))
}
return nil
}
// pathEscape escapes s so it can be used in a path.
// That is, it escapes things like ? and # (which really shouldn't appear anyway).
// It does not escape / to %2F: our REST API is designed so that / can be left as is.
func pathEscape(s string) string {
return strings.ReplaceAll(url.PathEscape(s), "%2F", "/")
}
View on GitHub (pinned to b6b368adc5)