hashicorp/packer · error

failed to describe plugin binary %q: %s

Error message

failed to describe plugin binary %q: %s

What it means

checkVersion runs the freshly downloaded plugin binary with `describe` to read its self-reported version; if that command fails, this ContinuableInstallError is returned so InstallLatest skips to the next candidate version. The binary couldn't be executed or produced no usable describe output.

Source

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

func GetPluginDescription(pluginPath string) (pluginsdk.SetDescription, error) {
	out, err := exec.Command(pluginPath, "describe").Output()
	if err != nil {
		return pluginsdk.SetDescription{}, err
	}

	desc := pluginsdk.SetDescription{}
	err = json.Unmarshal(out, &desc)

	return desc, err
}

// checkVersion checks the described version of a plugin binary against the requested version constriant.
// A ContinuableInstallError is returned upon a version mismatch to indicate that the caller should try the next
// available version. A PrereleaseInstallError is returned to indicate an unsupported version install.
func checkVersion(binPath string, identifier string, version *goversion.Version) error {
	desc, err := GetPluginDescription(binPath)
	if err != nil {
		err := fmt.Errorf("failed to describe plugin binary %q: %s", binPath, err)
		return &ContinuableInstallError{Err: err}
	}
	descVersion, err := goversion.NewSemver(desc.Version)
	if err != nil {
		err := fmt.Errorf("invalid self-reported version %q: %s", desc.Version, err)
		return &ContinuableInstallError{Err: err}
	}
	if descVersion.Core().Compare(version.Core()) != 0 {
		err := fmt.Errorf("binary reported version (%q) is different from the expected %q, skipping", desc.Version, version.String())
		return &ContinuableInstallError{Err: err}
	}
	if version.Prerelease() != "" {
		return &PrereleaseInstallError{
			PluginSrc: identifier,
			Err:       errors.New("binary reported a pre-release version of " + version.String()),
		}
	}
	// Since only final releases can be installed remotely, a non-empty prerelease version

View on GitHub (pinned to eb36e3c3e4)

Solutions

  1. Try running the binary directly: <plugin-path> describe — the OS error names the real cause
  2. Check the binary architecture matches the host (file <plugin-path>) and re-init to re-download the right asset
  3. Remount or relocate the plugin directory if it's on a noexec filesystem
  4. Delete the plugin from ~/.packer.d/plugins and re-run `packer init` for a clean download
  5. Update to a packer/plugin release where assets are correctly labeled for your platform

Example fix

// before (noexec /tmp)
$ packer init .
Error: failed to describe plugin binary "/tmp/packer-plugin...": fork/exec ...: permission denied
// after
export PACKER_PLUGIN_PATH=$HOME/.packer.d  # on exec-mounted fs
packer init .
Defensive patterns

Strategy: validation

Validate before calling

// after a failure, validate the binary can execute at all
import "os/exec"
out, err := exec.Command(binPath, "describe").CombinedOutput()
if err != nil {
    // e.g. fork/exec: permission denied => noexec mount or missing exec bit
    // e.g. exec format error => wrong architecture
    return fmt.Errorf("plugin binary %s not runnable: %v: %s", binPath, err, out)
}

Prevention

When it happens

Trigger: GetPluginDescription(binPath) fails — binary not executable (download lost the exec bit / noexec mount), corrupted/truncated download, wrong architecture for the host, or the plugin crashes on `describe`.

Common situations: Downloading a darwin/windows binary on linux due to mislabeled release assets; /home or /tmp mounted noexec; partial download from a flaky network; malicious/corrupted binary that fails to start.

Related errors


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