helm/helm · error

failed to create plugin tarball: %w

Error message

failed to create plugin tarball: %w

What it means

The output file was created successfully, but plugin.CreatePluginTarball (internal/plugin/sign.go:105) failed while walking the plugin source directory and copying files into the tar writer. The half-written archive is cleaned up with os.Remove before the error is returned. Causes are per-file problems inside the plugin directory: unreadable files, permission bits, broken symlinks.

Source

Thrown at pkg/cmd/plugin_package.go:139

		// User explicitly disabled signing
		fmt.Fprint(out, "WARNING: Skipping plugin signing. This is not recommended for plugins intended for distribution.\n")
	}

	// Now create the tarball (only after signing prerequisites are met)
	// Use plugin metadata for filename: PLUGIN_NAME-SEMVER.tgz
	metadata := pluginMeta.Metadata()
	filename := fmt.Sprintf("%s-%s.tgz", metadata.Name, metadata.Version)
	tarballPath := filepath.Join(o.destination, filename)

	tarFile, err := os.Create(tarballPath)
	if err != nil {
		return fmt.Errorf("failed to create tarball: %w", err)
	}
	defer tarFile.Close()

	if err := plugin.CreatePluginTarball(o.pluginPath, metadata.Name, tarFile); err != nil {
		os.Remove(tarballPath)
		return fmt.Errorf("failed to create plugin tarball: %w", err)
	}
	tarFile.Close() // Ensure file is closed before signing

	// If signing was requested, sign the tarball
	if o.sign {
		// Read the tarball data
		tarballData, err := os.ReadFile(tarballPath)
		if err != nil {
			os.Remove(tarballPath)
			return fmt.Errorf("failed to read tarball for signing: %w", err)
		}

		// Sign the plugin tarball data
		sig, err := plugin.SignPlugin(tarballData, filepath.Base(tarballPath), signer)
		if err != nil {
			os.Remove(tarballPath)
			return fmt.Errorf("failed to sign plugin: %w", err)
		}

View on GitHub (pinned to 2a29f1770b)

Solutions

  1. Check the wrapped error to identify which file failed to read
  2. Fix readability: `chmod -R u+rX ./my-plugin` and repair/remove broken symlinks
  3. Re-run once concurrent writes to the plugin directory have stopped

Example fix

# before
helm plugin package ./my-plugin --destination ./dist
# error: failed to create plugin tarball: open ./my-plugin/bin/helm-my-plugin: permission denied

# after
chmod -R u+rX ./my-plugin && helm plugin package ./my-plugin --destination ./dist
Defensive patterns

Strategy: try-catch

Validate before calling

func checkPluginFilesReadable(root string) error {
    return filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
        if err != nil {
            return err
        }
        if info.Mode().IsRegular() && info.Mode().Perm()&0o400 == 0 {
            return fmt.Errorf("file not readable: %s", p)
        }
        if info.Mode()&os.ModeSymlink != 0 {
            if _, err := os.Stat(p); err != nil {
                return fmt.Errorf("broken symlink: %s", p)
            }
        }
        return nil
    })
}

Try / catch

if err := runPluginPackage(args); err != nil {
    if strings.Contains(err.Error(), "failed to create plugin tarball") {
        // tarball was cleaned up by helm; fix file perms and retry once
        _ = exec.Command("chmod", "-R", "u+rX", pluginDir).Run()
        return runPluginPackage(args)
    }
    return err
}

Prevention

When it happens

Trigger: A file inside the plugin dir with mode 000 or owned by another user; a symlink pointing to a nonexistent target; a file deleted concurrently while the tar walk is in progress.

Common situations: Restrictive umask or ownership after copying plugin files in CI; committed broken symlinks (e.g. node_modules style link farms); antivirus quarantining a binary mid-read on Windows.

Related errors


AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15). Data as JSON: /api/errors/8edb28898351981d. Report an issue: GitHub.