{"record":{"id":"e11f5511ac213b77","repo":"larksuite/cli","slug":"gzip-w","errorCode":null,"errorMessage":"gzip: %w","messagePattern":"gzip: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shortcuts/apps/plugin_common.go","lineNumber":355,"sourceCode":"\tvar pkg map[string]interface{}\n\tif err := json.Unmarshal(data, &pkg); err != nil {\n\t\treturn \"\"\n\t}\n\tv, _ := pkg[\"version\"].(string)\n\treturn v\n}\n\n// ── tgz extraction ──\n\nconst pluginExtractMaxBytes = 10 * 1024 * 1024\n\n// pluginExtractTGZ extracts a gzipped tar archive into destDir, stripping the\n// first path component (npm convention: tarballs contain a \"package/\" prefix).\n// Path traversal entries are silently skipped.\nfunc pluginExtractTGZ(r io.Reader, destDir string) error {\n\tgz, err := gzip.NewReader(r)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"gzip: %w\", err) //nolint:forbidigo // intermediate helper error; callers wrap as typed\n\t}\n\tdefer gz.Close()\n\n\tcleanDest := filepath.Clean(destDir) + string(filepath.Separator)\n\ttr := tar.NewReader(gz)\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"tar: %w\", err) //nolint:forbidigo // intermediate helper error; callers wrap as typed\n\t\t}\n\n\t\tname := pluginStripFirstComponent(hdr.Name)\n\t\tif name == \"\" {\n\t\t\tcontinue\n\t\t}","sourceCodeStart":337,"sourceCodeEnd":373,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/shortcuts/apps/plugin_common.go#L337-L373","documentation":"pluginExtractTGZ wraps a gzip.NewReader failure with 'gzip: %w'. The tarball passed to a plugin install is not valid gzip data (bad magic, truncated stream, or an HTML error page saved as .tgz). Per the nolint comment this is an intermediate error; callers wrap it as a typed error.","triggerScenarios":"Plugin install with a corrupted download, a non-gzip file (e.g. an HTML 404 page or plain tar) named *.tgz, or an interrupted download leaving a truncated archive.","commonSituations":"Corporate proxies returning error pages, offline/partial npm cache, or pointing the installer at a manually edited archive.","solutions":["Re-download the plugin tarball and verify integrity (checksum or gzip -t)","Confirm the file is actually gzip: `file plugin.tgz` should say 'gzip compressed data'","If the URL requires auth, fetch with credentials first and pass the local valid tarball"],"exampleFix":"// before\ncurl -o plugin.tgz https://example.invalid/plugin.tgz  # saved HTML 404\nlark-cli plugin install --file plugin.tgz\n// after\ncurl -fSL -o plugin.tgz https://registry.example/plugin.tgz && gzip -t plugin.tgz","handlingStrategy":"validation","validationCode":"f, err := os.Open(tarball)\nif err == nil {\n\tmagic := make([]byte, 2)\n\tio.ReadFull(f, magic) // gzip magic 0x1f 0x8b\n\tvalid := magic[0] == 0x1f && magic[1] == 0x8b\n\tf.Close()\n\t_ = valid\n}","typeGuard":"func looksLikeGzip(head []byte) bool { return len(head) >= 2 && head[0] == 0x1f && head[1] == 0x8b }","tryCatchPattern":"if _, err := gzip.NewReader(r); err != nil {\n\t// fail fast: re-download the tarball and verify its checksum\n}","preventionTips":["Verify tarball checksums after download","Use curl -f (or equivalent) so HTTP error bodies are not saved as .tgz","Run `gzip -t plugin.tgz` before installing"],"tags":["archive","gzip","plugin-install"],"backgroundTag":"invalid-gzip-archive","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}