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.

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)

Solutions

  1. 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.
  2. 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).
  3. 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.
  4. 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.
  5. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/06b5331273c01d38. Report an issue: GitHub.