jeessy2/ddns-go · error
zip 文件
Error message
%w zip 文件: %s
What it means
After buffering, unzip opens the data as a zip archive with zip.NewReader; if the bytes are not a valid zip archive, it returns errCannotDecompressFile wrapped with this message and the underlying zip error. It indicates the downloaded content is corrupt or not actually zip format.
Solutions
- Verify the downloaded file is a real zip (file/unzip on disk, or check first bytes for PK magic)
- Check the release URL returns the actual zip asset, not an HTML error page
- Re-download the asset (truncated downloads commonly corrupt archives); confirm via errors.Is(err, errCannotDecompressFile)
Defensive patterns
Strategy: validation
Validate before calling
// Check zip magic bytes before unzipping
head := make([]byte, 4)
if n, _ := io.ReadFull(src, head); n < 4 || string(head[:2]) != "PK" {
return fmt.Errorf("not a zip archive")
} Try / catch
r, err := unzip(src, cmd)
if err != nil {
if errors.Is(err, errCannotDecompressFile) {
log.Errorf("downloaded artifact is not a valid zip: %v", err)
return errCorruptAsset
}
return err
} Prevention
- Verify asset checksums after download before decompressing
- Confirm the URL serves the zip asset, not an HTML error page
- Check first bytes for the PK magic number
- Pin release asset URLs and re-download on corruption
When it happens
Trigger: Self-update downloads a .zip archive whose bytes fail zip.NewReader — e.g. the URL returned an HTML error page, a partial download, or the asset is actually gzip/tar not zip.
Common situations: Release assets replaced or misnamed on the host; CDN/proxy returning an error page with 200; truncated download saved as .zip; pointing the updater at the wrong artifact.
Related errors
AI-assisted analysis of jeessy2/ddns-go@5874c2e666 (2026-09-03).
Data as JSON: /api/errors/b605881bb14f13af.
Report an issue: GitHub.
Appendix: source
Thrown at util/update/decompress.go:51
return decompress(src, cmd)
}
}
log.Print("It's not a compressed file, skip decompressing")
return src, nil
}
func unzip(src io.Reader, cmd string) (io.Reader, error) {
// 解压 Zip 格式时需要文件大小。
// 因此我们需要先将 HTTP 响应读取到缓冲区中。
buf, err := io.ReadAll(src)
if err != nil {
return nil, fmt.Errorf("%w zip 文件: %v", errCannotDecompressFile, err)
}
r := bytes.NewReader(buf)
z, err := zip.NewReader(r, r.Size())
if err != nil {
return nil, fmt.Errorf("%w zip 文件: %s", errCannotDecompressFile, err)
}
for _, file := range z.File {
_, name := filepath.Split(file.Name)
if !file.FileInfo().IsDir() && matchExecutableName(cmd, name) {
return file.Open()
}
}
return nil, fmt.Errorf("在 zip 文件中%w:%q", errExecutableNotFoundInArchive, cmd)
}
func untar(src io.Reader, cmd string) (io.Reader, error) {
gz, err := gzip.NewReader(src)
if err != nil {
return nil, fmt.Errorf("%w tar.gz 文件: %s", errCannotDecompressFile, err)
}
View on GitHub (pinned to 5874c2e666)