hashicorp/packer · error

Invalid remote protocol: %q, expected something like '%s.%s'

Error message

Invalid remote protocol: %q, expected something like '%s.%s'

What it means

NewAPIVersion() parses a remote protocol version string like "x5.0" into an APIVersion. After trimming the "x" prefix it requires at least two dot-separated components (major.minor). Strings with fewer parts cannot represent a valid protocol version and are rejected.

Source

Thrown at packer/plugin-getter/plugins.go:489

// ExpectedZipFilename is the filename of the zip we expect to find, the
// value is known only after parsing the checksum file file.
func (gp *GetOptions) ExpectedZipFilename() string {
	return gp.expectedZipFilename
}

type APIVersion struct {
	Major int
	Minor int
}

func NewAPIVersion(apiVersion string) (APIVersion, error) {
	ver := APIVersion{}

	apiVersion = strings.TrimPrefix(strings.TrimSpace(apiVersion), "x")
	parts := strings.Split(apiVersion, ".")
	if len(parts) < 2 {
		return ver, fmt.Errorf(
			"Invalid remote protocol: %q, expected something like '%s.%s'",
			apiVersion, pluginsdk.APIVersionMajor, pluginsdk.APIVersionMinor,
		)
	}

	vMajor, err := strconv.Atoi(parts[0])
	if err != nil {
		return ver, err
	}
	ver.Major = vMajor

	vMinor, err := strconv.Atoi(parts[1])
	if err != nil {
		return ver, err
	}
	ver.Minor = vMinor

	return ver, nil

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Ensure the plugin binary/filename embeds a full x{major}.{minor} protocol version (e.g. x5.0); rebuild with the current packer-plugin-sdk.
  2. Fix the asset/checksum filename so the _x{M}.{N}_ segment is present and well-formed.
  3. Upgrade the plugin to a release produced by the standard SDK tooling.

Example fix

// before
packer-plugin-foo_1.0.0_x5_linux_amd64.zip
// after
packer-plugin-foo_1.0.0_x5.0_linux_amd64.zip
Defensive patterns

Strategy: validation

Validate before calling

trimmed := strings.TrimPrefix(strings.TrimSpace(s), "x")
if len(strings.Split(trimmed, ".")) < 2 {
	return fmt.Errorf("protocol version %q must be x{major}.{minor}", s)
}

Type guard

func isCompleteProtVersion(s string) bool {
	parts := strings.Split(strings.TrimPrefix(strings.TrimSpace(s), "x"), ".")
	return len(parts) >= 2 && parts[0] != "" && parts[1] != ""
}

Try / catch

av, err := NewAPIVersion(prot)
if err != nil {
	if strings.Contains(err.Error(), "Invalid remote protocol") {
		// treat asset/binary as produced by nonstandard tooling; skip it
	}
}

Prevention

When it happens

Trigger: Calling NewAPIVersion with a string like "5", "", "x", or "x5" — i.e. the protocol version advertised by a plugin binary or embedded in a filename lacks the major.minor form.

Common situations: A plugin built with a very old or custom SDK that reports a single-number protocol version; a corrupted plugin binary filename like foo_1.0.0_x5_linux_amd64 (missing minor); hand-edited checksum entries.

Related errors


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