hashicorp/packer · error

malformed filename expected %s{version}_{os}_{arch}

Error message

malformed filename expected %s{version}_{os}_{arch}

What it means

Init parses a downloaded plugin binary's filename to extract version, OS, and arch, expecting the naming scheme {prefix}_{version}_{os}_{arch}[_ext] (e.g. packer-plugin-docker_1.1.1_freebsd_amd64.zip). If after stripping the extension the underscore-split yields fewer than 3 parts, the filename does not follow the official plugin naming convention and Init fails.

Source

Thrown at packer/plugin-getter/release/getter.go:149

// Init method : a file inside will look like so:
//
//	packer-plugin-comment_0.2.12_freebsd_amd64.zip
func (g *Getter) Init(req *plugingetter.Requirement, entry *plugingetter.ChecksumFileEntry) error {
	filename := entry.Filename
	//remove the test line below where hardcoded prefix being used
	res := strings.TrimPrefix(filename, req.FilenamePrefix())
	// res now looks like v0.2.12_freebsd_amd64.zip

	entry.Ext = filepath.Ext(res)

	res = strings.TrimSuffix(res, entry.Ext)
	// res now looks like 0.2.12_freebsd_amd64

	parts := strings.Split(res, "_")
	// ["0.2.12", "freebsd", "amd64"]
	if len(parts) < 3 {
		return fmt.Errorf("malformed filename expected %s{version}_{os}_{arch}", req.FilenamePrefix())
	}

	entry.BinVersion, entry.Os, entry.Arch = parts[0], parts[1], parts[2]
	entry.BinVersion = strings.TrimPrefix(entry.BinVersion, "v")

	return nil
}

func (g *Getter) Validate(opt plugingetter.GetOptions, expectedVersion string, installOpts plugingetter.BinaryInstallationOptions, entry *plugingetter.ChecksumFileEntry) error {

	if entry.BinVersion != expectedVersion {
		return fmt.Errorf("wrong version: %s does not match expected %s", entry.BinVersion, expectedVersion)
	}
	if entry.Os != installOpts.OS || entry.Arch != installOpts.ARCH {
		return fmt.Errorf("wrong system, expected %s_%s got %s_%s", installOpts.OS, installOpts.ARCH, entry.Os, entry.Arch)
	}

	manifest, err := g.Get("meta", opt)

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Rename the plugin file to the canonical form {prefix}_{version}_{os}_{arch}.zip (e.g. packer-plugin-docker_1.1.1_linux_amd64.zip).
  2. Re-download the plugin via `packer plugins install` so the officially named release zip is used.
  3. If it's a custom plugin, update its release pipeline to emit HashiCorp-convention filenames.

Example fix

// before (file on disk)
packer-plugin-docker_1.1.1.zip
// after
packer-plugin-docker_1.1.1_linux_amd64.zip
Defensive patterns

Strategy: validation

Validate before calling

name := strings.TrimSuffix(filepath.Base(filename), filepath.Ext(filename))
parts := strings.Split(name, "_")
if len(parts) < 3 {
    return fmt.Errorf("rename %q to prefix_version_os_arch before installing", filename)
}

Try / catch

if err := g.Init(req, opts); err != nil {
    if strings.HasPrefix(err.Error(), "malformed filename") {
        // rename the binary to the canonical scheme and retry once
    }
}

Prevention

When it happens

Trigger: Getter.Init is given a ChecksumFileEntry whose Filename, after removing the prefix and extension and splitting on "_", has fewer than 3 segments — e.g. "packer-plugin-docker_1.1.1.zip" (no os/arch) or a bare version string.

Common situations: Manually downloaded or self-renamed plugin binaries placed in PACKER_PLUGIN_PATH; third-party plugin releases that don't follow HashiCorp's naming convention; old/custom plugin builds produced before the standardized naming scheme.

Understand the failure class

Related errors


AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05). Data as JSON: /api/errors/12202dcb169ab3fc. Report an issue: GitHub.