hashicorp/packer · error

malformed filename expected %s{version}_x{protocol-version}_

Error message

malformed filename expected %s{version}_x{protocol-version}_{os}_{arch}

What it means

Init() parses a checksum-file entry filename into its components (binary version, protocol version, OS, arch) after stripping the prefix and extension. The remaining name must have at least 4 underscore-separated parts shaped like {prefix}vX.Y.Z_xM.N_os_arch. Fewer parts means the filename does not follow the Packer plugin binary naming convention.

Source

Thrown at packer/plugin-getter/github/getter.go:313

}

// Init method: a file inside will look like so:
//
//	packer-plugin-comment_v0.2.12_x5.0_freebsd_amd64.zip
func (g *Getter) Init(req *plugingetter.Requirement, entry *plugingetter.ChecksumFileEntry) error {
	filename := entry.Filename
	res := strings.TrimPrefix(filename, req.FilenamePrefix())
	// res now looks like v0.2.12_x5.0_freebsd_amd64.zip

	entry.Ext = filepath.Ext(res)

	res = strings.TrimSuffix(res, entry.Ext)
	// res now looks like v0.2.12_x5.0_freebsd_amd64

	parts := strings.Split(res, "_")
	// ["v0.2.12", "x5.0", "freebsd", "amd64"]
	if len(parts) < 4 {
		return fmt.Errorf("malformed filename expected %s{version}_x{protocol-version}_{os}_{arch}", req.FilenamePrefix())
	}

	entry.BinVersion, entry.ProtVersion, entry.Os, entry.Arch = parts[0], parts[1], parts[2], parts[3]

	return nil
}

func (g *Getter) Validate(opt plugingetter.GetOptions, expectedVersion string, installOpts plugingetter.BinaryInstallationOptions, entry *plugingetter.ChecksumFileEntry) error {
	expectedBinVersion := "v" + expectedVersion
	if entry.BinVersion != expectedBinVersion {
		return fmt.Errorf("wrong version: %s does not match expected %s", entry.BinVersion, expectedBinVersion)
	}
	if entry.Os != installOpts.OS || entry.Arch != installOpts.ARCH {
		return fmt.Errorf("wrong system, expected %s_%s", installOpts.OS, installOpts.ARCH)
	}

	return installOpts.CheckProtocolVersion(entry.ProtVersion)
}

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Rename the release asset to the standard form: packer-plugin-<name>_<version>_x<protocol>_<os>_<arch>.zip and regenerate the SHA256SUM file.
  2. Rebuild the plugin release with the current packer-plugin-sdk (go build via the SDK scaffolding) so the filename embeds version, protocol, OS, and arch.
  3. Verify the checksums file on the release matches the actual asset names.

Example fix

// before (asset name)
packer-plugin-foo_1.0.0.zip
// after
packer-plugin-foo_1.0.0_x5.0_linux_amd64.zip
Defensive patterns

Strategy: validation

Validate before calling

base := strings.TrimSuffix(strings.TrimPrefix(fname, prefix), ext)
parts := strings.Split(base, "_")
if len(parts) < 4 {
	return fmt.Errorf("asset %q does not match {version}_x{proto}_{os}_{arch}", fname)
}

Type guard

func isWellFormedPluginAsset(fname, prefix, ext string) bool {
	parts := strings.Split(strings.TrimSuffix(strings.TrimPrefix(fname, prefix), ext), "_")
	return len(parts) >= 4 && strings.HasPrefix(parts[1], "x")
}

Try / catch

if err := getter.Init(req, entries); err != nil {
	if strings.Contains(err.Error(), "malformed filename") {
		log.Printf("skipping nonstandard asset: %v", err)
	}
}

Prevention

When it happens

Trigger: Getter.Init() receives a ChecksumFileEntry whose filename, after trimming the prefix (e.g. packer-plugin-), extension (.zip), and splitting on "_", yields fewer than 4 parts — e.g. "packer-plugin-name_v1.0.0.zip" with no _x5.0_linux_amd64 suffix.

Common situations: A hand-rolled or renamed release asset in a GitHub checksums file; a plugin release built with an old or nonstandard naming scheme; a custom/renamed plugin published outside the SDK's naming tooling; corrupted or edited SHA256SUM files.

Understand the failure class

Related errors


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