{"record":{"id":"06b5331273c01d38","repo":"golang/go","slug":"downloaded-zip-file-too-large-06b533","errorCode":null,"errorMessage":"downloaded zip file too large","messagePattern":"downloaded zip file too large","errorType":"exception","errorClass":"module.VersionError","httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/modfetch/proxy.go","lineNumber":446,"sourceCode":"\tif err != nil {\n\t\treturn p.versionError(version, err)\n\t}\n\tpath := \"@v/\" + encVer + \".zip\"\n\tbody, redactedURL, err := p.getBody(ctx, path)\n\tif err != nil {\n\t\treturn p.versionError(version, err)\n\t}\n\tdefer body.Close()\n\n\tlr := &io.LimitedReader{R: body, N: codehost.MaxZipFile + 1}\n\tif _, err := io.Copy(dst, lr); err != nil {\n\t\t// net/http doesn't add context to Body read errors, so add it here.\n\t\t// (See https://go.dev/issue/52727.)\n\t\terr = &url.Error{Op: \"read\", URL: redactedURL, Err: err}\n\t\treturn p.versionError(version, err)\n\t}\n\tif lr.N <= 0 {\n\t\treturn p.versionError(version, fmt.Errorf(\"downloaded zip file too large\"))\n\t}\n\treturn nil\n}\n\n// pathEscape escapes s so it can be used in a path.\n// That is, it escapes things like ? and # (which really shouldn't appear anyway).\n// It does not escape / to %2F: our REST API is designed so that / can be left as is.\nfunc pathEscape(s string) string {\n\treturn strings.ReplaceAll(url.PathEscape(s), \"%2F\", \"/\")\n}\n","sourceCodeStart":428,"sourceCodeEnd":457,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/modfetch/proxy.go#L428-L457","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: module ships 600MB of model weights in /assets\n// module structure: mymodule/assets/weights.bin (500MB+)\n\n// after: fetch weights separately at runtime or build time\n// go.mod stays small; weights downloaded via a Makefile target\npackage mymodule\n\n//go:embed config.json\nvar configBytes []byte // small file only\n\n// large files fetched separately:\n// $ make download-weights","handlingStrategy":"validation","validationCode":"// Check module size before downloading (if proxy provides Content-Length)\n// Shell: curl -sI \"https://proxy.golang.org/<module>/@v/<version>.zip\" | grep -i content-length\n// Go wrapper:\nfunc checkModuleSize(proxyURL, modPath, version string) error {\n    url := fmt.Sprintf(\"%s/%s/@v/%s.zip\", proxyURL, modPath, version)\n    resp, err := http.Head(url)\n    if err != nil { return err }\n    defer resp.Body.Close()\n    if resp.ContentLength > 500*1024*1024 {\n        return fmt.Errorf(\"module zip is %d bytes, exceeds 500 MiB limit\", resp.ContentLength)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Parse go command stderr for this specific error\nif strings.Contains(stderr, \"downloaded zip file too large\") {\n    // Module exceeds hard limit; cannot be worked around via config\n    // Recommend splitting the module or using an older/smaller version\n}","preventionTips":["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"],"tags":["go-modules","go-proxy","download-limit","size-ceiling","network"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}