Composer不重试损坏ZIP,因SHA256校验失败发生在HTTP下载之后,属主动安全拦截而非网络故障;需删vendor和composer.lock、清缓存、切源重拉。

Composer 不会自动重试损坏的 ZIP 文件——它在解压前就校验 SHA256,不匹配直接报 checksum mismatch 或 Failed to extract vendor/package-name,然后终止,根本不会触发重试逻辑。
为什么“损坏 ZIP”不走重试流程
重试机制只作用于 HTTP 层错误(如 CURL error 28、503),而 ZIP 损坏属于下载后校验失败,发生在 CurlDownloader 之后的解包阶段。此时请求早已完成,Composer 认为“数据已拿到”,只是内容不可信,安全策略优先于容错策略。
-
checksum mismatch是主动拦截,不是临时故障,因此不满足重试前提 - 损坏 ZIP 通常源于镜像同步滞后、tag 被重推、或缓存写入中断,这些都不是网络抖动,重试无意义
- 即使你设了
--retries=10,对已缓存的坏 ZIP 完全无效——Composer 根本不发起新请求
如何确认是 ZIP 损坏而非网络超时
看错误信息关键词,而不是日志里有没有“retry”字样:
- 出现
unable to open archive、Content-Length mismatch、Invalid argument supplied for foreach()(因installed.json截断)→ 基本锁定 ZIP 损坏 - 出现
cURL error 28、Connection refused、Operation timed out→ 才是网络层问题,重试可能生效 - 用
ls -la $(composer config --global cache-dir)/files/查对应包的 ZIP 文件大小:小于 10KB 或时间戳早于你最近一次composer install→ 极大概率损坏
真正有效的“重试”操作不是重跑命令,而是清+切+重拉
所谓“重试”,实际是一套三步清除动作,绕过所有缓存路径和残留元数据:
- 删干净:
rm -rf vendor composer.lock(Windows 用rmdir /s vendor & del composer.lock) - 清缓存:
composer clear-cache,再手动确认$(composer config --global cache-dir)/files/下无残留 ZIP - 切源重拉:
composer config -g --unset repos.packagist(切回官方源保真),再composer install --no-cache
如果必须用国内镜像,等阿里云/腾讯云同步完成(查 curl -I https://mirrors.aliyun.com/composer/packages.json | grep Last-Modified),再 composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/。
CI/CD 中避免 ZIP 损坏的关键细节
流水线环境容易复现损坏,因为缓存目录常被挂载复用,且 --no-cache 不足以清除元数据污染:
- 务必设置
COMPOSER_CACHE_DIR=/dev/null,彻底禁用缓存目录,而不是依赖clear-cache - 不要只删
vendor——composer.lock若含旧哈希,重装仍失败;必须双删 - 加
--prefer-dist强制走 ZIP 包,避开 git clone 的不可控性;但前提是镜像源提供 dist 归档(私有包常不提供)
最易被忽略的一点:镜像 URL 配错(比如末尾多斜杠)、或项目级 repositories 覆盖全局配置,会导致你以为在走镜像,实际请求发往 packagist.org,下载慢→中断→ZIP 损坏→死循环。











