{"record":{"id":"16c07ef1df930970","repo":"jeessy2/ddns-go","slug":"w-tar-gz-s","errorCode":null,"errorMessage":"%w tar.gz 文件: %s","messagePattern":"%w tar\\.gz 文件: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/update/decompress.go","lineNumber":67,"sourceCode":"\tz, err := zip.NewReader(r, r.Size())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w zip 文件: %s\", errCannotDecompressFile, err)\n\t}\n\n\tfor _, file := range z.File {\n\t\t_, name := filepath.Split(file.Name)\n\t\tif !file.FileInfo().IsDir() && matchExecutableName(cmd, name) {\n\t\t\treturn file.Open()\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"在 zip 文件中%w：%q\", errExecutableNotFoundInArchive, cmd)\n}\n\nfunc untar(src io.Reader, cmd string) (io.Reader, error) {\n\tgz, err := gzip.NewReader(src)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w tar.gz 文件: %s\", errCannotDecompressFile, err)\n\t}\n\n\tt := tar.NewReader(gz)\n\tfor {\n\t\th, err := t.Next()\n\t\tif errors.Is(err, io.EOF) {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%w tar.gz 文件：%s\", errCannotDecompressFile, err)\n\t\t}\n\t\t_, name := filepath.Split(h.Name)\n\t\tif matchExecutableName(cmd, name) {\n\t\t\treturn t, nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"在 tar.gz 文件中%w：%q\", errExecutableNotFoundInArchive, cmd)\n}","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/jeessy2/ddns-go/blob/5874c2e6667c69357ab95079421131104bd3fcae/util/update/decompress.go#L49-L85","documentation":"untar first wraps the source in gzip.NewReader; if the stream is not valid gzip data, it returns errCannotDecompressFile wrapped with this message and the gzip error. It signals the downloaded .tar.gz artifact is not actually gzip-compressed.","triggerScenarios":"Self-update downloads a .tar.gz asset whose bytes fail gzip.NewReader — server returned an HTML/text error page, the file is uncompressed tar, or the download was truncated/corrupted.","commonSituations":"Release URL pointing at an error page or wrong artifact; proxy stripping/altering content-encoding; partial download of a large tarball.","solutions":["Verify the downloaded file starts with the gzip magic bytes (1f 8b) and is a real .tar.gz","Confirm the release URL serves the actual tar.gz asset, not an error page","Re-download the asset; use errors.Is(err, errCannotDecompressFile) to identify this family"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Check gzip magic bytes before untarring\nhead := make([]byte, 2)\nif n, _ := io.ReadFull(src, head); n < 2 || head[0] != 0x1f || head[1] != 0x8b {\n    return fmt.Errorf(\"not gzip data\")\n}","typeGuard":null,"tryCatchPattern":"r, err := untar(src, cmd)\nif err != nil {\n    if errors.Is(err, errCannotDecompressFile) {\n        log.Errorf(\"downloaded artifact is not valid tar.gz: %v\", err)\n        return errCorruptAsset\n    }\n    return err\n}","preventionTips":["Verify asset checksums after download before decompressing","Check first bytes for the 0x1f 0x8b gzip magic","Confirm the URL serves the real .tar.gz, not an error page","Re-download truncated tarballs before retrying"],"tags":["tar","gzip","decompression","corrupt-archive"],"backgroundTag":"archive-decompression-failed","analyzedSha":"5874c2e6667c69357ab95079421131104bd3fcae","analyzedAt":"2026-09-03T15:41:16.799Z","contentChangedAt":"2026-09-03T15:41:16.799Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}