larksuite/cli · error

gzip: %w

Error message

gzip: %w

What it means

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.

Source

Thrown at shortcuts/apps/plugin_common.go:355

	var pkg map[string]interface{}
	if err := json.Unmarshal(data, &pkg); err != nil {
		return ""
	}
	v, _ := pkg["version"].(string)
	return v
}

// ── tgz extraction ──

const pluginExtractMaxBytes = 10 * 1024 * 1024

// pluginExtractTGZ extracts a gzipped tar archive into destDir, stripping the
// first path component (npm convention: tarballs contain a "package/" prefix).
// Path traversal entries are silently skipped.
func pluginExtractTGZ(r io.Reader, destDir string) error {
	gz, err := gzip.NewReader(r)
	if err != nil {
		return fmt.Errorf("gzip: %w", err) //nolint:forbidigo // intermediate helper error; callers wrap as typed
	}
	defer gz.Close()

	cleanDest := filepath.Clean(destDir) + string(filepath.Separator)
	tr := tar.NewReader(gz)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			return fmt.Errorf("tar: %w", err) //nolint:forbidigo // intermediate helper error; callers wrap as typed
		}

		name := pluginStripFirstComponent(hdr.Name)
		if name == "" {
			continue
		}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Re-download the plugin tarball and verify integrity (checksum or gzip -t)
  2. Confirm the file is actually gzip: `file plugin.tgz` should say 'gzip compressed data'
  3. If the URL requires auth, fetch with credentials first and pass the local valid tarball

Example fix

// before
curl -o plugin.tgz https://example.invalid/plugin.tgz  # saved HTML 404
lark-cli plugin install --file plugin.tgz
// after
curl -fSL -o plugin.tgz https://registry.example/plugin.tgz && gzip -t plugin.tgz
Defensive patterns

Strategy: validation

Validate before calling

f, err := os.Open(tarball)
if err == nil {
	magic := make([]byte, 2)
	io.ReadFull(f, magic) // gzip magic 0x1f 0x8b
	valid := magic[0] == 0x1f && magic[1] == 0x8b
	f.Close()
	_ = valid
}

Type guard

func looksLikeGzip(head []byte) bool { return len(head) >= 2 && head[0] == 0x1f && head[1] == 0x8b }

Try / catch

if _, err := gzip.NewReader(r); err != nil {
	// fail fast: re-download the tarball and verify its checksum
}

Prevention

When it happens

Trigger: 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.

Common situations: Corporate proxies returning error pages, offline/partial npm cache, or pointing the installer at a manually edited archive.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/e11f5511ac213b77. Report an issue: GitHub.