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
- Rename the plugin file to the canonical form {prefix}_{version}_{os}_{arch}.zip (e.g. packer-plugin-docker_1.1.1_linux_amd64.zip).
- Re-download the plugin via `packer plugins install` so the officially named release zip is used.
- 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
- Always install plugins via `packer plugins install`, never by manually renaming binaries.
- Keep plugin release pipelines emitting HashiCorp-convention filenames.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- malformed filename expected %s{version}_x{protocol-version}_
- %q not implemented
- wrong version: %s does not match expected %s
- wrong system, expected %s_%s got %s_%s
- malformed index.json: %w
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/12202dcb169ab3fc.
Report an issue: GitHub.