go mod download 报 invalid package header 是缓存污染导致的,本质是本地下载缓存中某个 .zip 文件开头字节损坏(如空文件、html 错误页),go 解包时读到非 zip 头所致;需手动清理 $gopath/pkg/mod/cache/download/ 下对应模块的 .zip/.info/.mod 文件,而非仅用 go clean -modcache。

go mod download 报 invalid package header 是缓存污染导致的
这类错误不是代码写错了,而是本地模块缓存里某个 .zip 文件开头字节损坏,Go 解包时读到非 ZIP 格式头(比如空文件、HTTP 404 响应体、代理返回的 HTML 错误页),就直接报 invalid package header。它常和 zip: not a valid zip file 一起出现,本质是缓存脏了。
- 先定位出问题模块:错误信息里一般带路径,如
github.com/some/pkg@v1.2.3 - 删掉对应缓存:执行
rm -rf $GOPATH/pkg/mod/cache/download/github.com/some/pkg/@v/v1.2.3.zip*(注意通配符*,连带 .info 和 .mod 一起删) - 不要只清
go clean -modcache:它删的是解压后的模块目录($GOPATH/pkg/mod/...),而问题在下载缓存层($GOPATH/pkg/mod/cache/download/...),必须手动删 zip 文件
GO111MODULE=on 但 still fallback 到 GOPATH 导致 header 解析失败
当当前目录在 $GOPATH/src 下,即使 GO111MODULE=on,Go 仍会退回到旧模式,尝试从 $GOPATH/src 读源码并解析 import 路径——此时若该路径下只有空文件或残留的旧结构,就会因读到空内容而触发 invalid package header。
- 检查当前路径:
pwd输出是否以$GOPATH/src/开头?是的话立刻cd出去,比如到~/projects/myapp - 确认模块初始化状态:
ls go.mod必须存在;不存在就先go mod init example.com/myapp - 验证模块模式生效:
go env GO111MODULE输出必须是on,不是auto或空
GOPROXY 返回非 ZIP 内容(如 HTML 登录页)引发 header 错误
某些私有代理或配置错误的镜像(比如误配成网页地址而非模块代理端点)会在请求失败时返回 HTML 页面(如 404 页面、登录跳转页),Go 下载后直接当 ZIP 解,自然报 invalid package header。
- 用
curl -I https://goproxy.cn/github.com/sirupsen/logrus/@v/v1.9.3.info测试代理是否返回200 OK和Content-Type: application/json - 若返回
302或text/html,说明代理地址错(例如把https://goproxy.cn误写成https://goproxy.cn/多了个斜杠,或指向了某个 Web 控制台) - 临时绕过代理验证:
GOPROXY=direct go mod download -v github.com/sirupsen/logrus@v1.9.3,如果成功,问题一定出在代理配置
replace 指向本地路径但目录结构缺失或无 go.mod
当 go.mod 中用了 replace github.com/a/b => ../local-b,而 ../local-b 目录下没有 go.mod 文件,或者 go.mod 里 module 名与 replace 声明不一致,Go 在解析时会尝试读取该路径下的“伪包”,结果读到空或无效内容,最终报 header 错误。
- 检查 replace 目标路径是否存在且可读:
ls -la ../local-b/go.mod - 确认
../local-b/go.mod第一行module声明与 replace 左侧完全一致(包括大小写和路径分隔符) - 如果只是想临时调试,改用
replace github.com/a/b => ./vendor/github.com/a/b(确保 vendor 下有完整模块结构)更稳妥
真正麻烦的不是报错本身,而是它不告诉你具体哪个文件坏了——得靠 go mod download -v 最后几行输出反推路径,再手动进 cache 目录翻 zip 文件头。每次遇到都得重新 grep 一遍,没法自动化。











