hashicorp/packer · error

Unrecognized remote plugin message: %s

Error message

Unrecognized remote plugin message: %s

What it means

The plugin client parses the plugin's handshake line, which must contain 4 pipe-separated fields (major version, minor version, network type, address). If the trimmed stdout line does not produce at least 4 fields, it is not a recognizable handshake, so Start fails with this error.

Source

Thrown at packer/plugin_client.go:337

	case <-timeout:
		err = errors.New("timeout while waiting for plugin to start")
	case <-exitCh:
		err = errors.New("plugin exited before we could connect")
	case lineBytes := <-linesCh:
		// Trim the line and split by "|" in order to get the parts of
		// the output.
		line := strings.TrimSpace(string(lineBytes))
		parts := strings.SplitN(line, "|", 4)
		if len(parts) == 3 {
			// In protocol version 4 and before, the protocol only had a Major
			// version
			err = fmt.Errorf("The protocol of this plugin (protocol version 4 " +
				"and lower) was deprecated, please use a newer version of this plugin." +
				"Or use an older version of Packer (pre 1.7) with this plugin.")
			return nil, err
		}
		if len(parts) < 4 {
			err = fmt.Errorf("Unrecognized remote plugin message: %s", line)
			return nil, err
		}
		pluginMajorAPIVersion, pluginMinorAPIVersion, network, netAddr := parts[0], parts[1], parts[2], parts[3]

		// Test the API versions
		if pluginMajorAPIVersion != pluginsdk.APIVersionMajor {
			err = fmt.Errorf("Incompatible API MAJOR version with plugin. "+
				"plugin MINOR API version: %s, Ours: %s", pluginMajorAPIVersion, pluginsdk.APIVersionMajor)
			return nil, err
		}
		if pluginMinorAPIVersion > pluginsdk.APIVersionMinor {
			err = fmt.Errorf("Incompatible API MINOR version with plugin. "+
				"plugin MINOR API version: %s, Ours: %s. Please upgrade Packer.", pluginMinorAPIVersion, pluginsdk.APIVersionMinor)
			return nil, err
		}

		switch network {
		case "tcp":

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Check that the configured binary path is actually a Packer plugin executable for the correct component type.
  2. Run the plugin binary manually and inspect its stdout for panics or stray output.
  3. Rebuild/reinstall the plugin from a clean, current packer-plugin-sdk version.
  4. Remove any code in the plugin that writes non-handshake data to stdout (use stderr for logging).

Example fix

// before: plugin prints to stdout in main()
fmt.Println("starting plugin...") // pollutes handshake channel
// after
fmt.Fprintln(os.Stderr, "starting plugin...") // stderr is safe for logging
Defensive patterns

Strategy: validation

Validate before calling

fi, _ := os.Stat(pluginPath)
if fi != nil && fi.Mode().IsRegular() && fi.Mode().Perm()&0o111 != 0 {
  // still verify it is a real plugin:
  out, _ := exec.Command(pluginPath, "packer-plugin").Output()
  isPlugin := strings.Count(strings.TrimSpace(string(out)), "|") >= 3
}

Try / catch

if _, err := client.Start(); err != nil {
  if strings.Contains(err.Error(), "Unrecognized remote plugin message") {
    log.Printf("%s is not a Packer plugin or crashed on startup: %v", path, err)
  }
}

Prevention

When it happens

Trigger: Client.Start() in packer/plugin_client.go receives a first stdout line from the plugin process that is not a `major|minor|network|addr` handshake: the binary prints diagnostics, logs, an error message, or nothing meaningful instead of the handshake.

Common situations: Executed a binary that is not a Packer plugin at all (e.g. a script, a shell, a README accidentally marked executable); plugin crashes before handshake and prints a panic; plugin's stdout is polluted by print statements from custom code; wrong binary specified via required_plugins or PACKER_PLUGIN_PATH.

Related errors


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