hashicorp/nomad · error

plugin provided no compatible API versions

Error message

plugin provided no compatible API versions

What it means

PluginLoader.selectApiVersion guard: the plugin's PluginInfoResponse carries an empty PluginApiVersions list, so no API version overlap with the agent is possible and the plugin is rejected as malformed.

Solutions

  1. Populate PluginApiVersions in the plugin's PluginInfoResponse, e.g. []string{"v1"}
  2. Verify against the plugin type's latest API constant (e.g. api.Version01) that the declared versions match what the plugin actually implements
  3. Rebuild the plugin binary/agent after the fix

Example fix

// before
return &base.PluginInfoResponse{Type: base.PluginTypeCSI}, nil
// after
return &base.PluginInfoResponse{Type: base.PluginTypeCSI, PluginApiVersions: []string{"v1"}}, nil
Defensive patterns

Strategy: validation

Validate before calling

if len(info.PluginApiVersions) == 0 {
    return errors.New("PluginApiVersions must list at least one version")
}

Type guard

func declaresApiVersions(info *base.PluginInfoResponse) bool {
    return info != nil && len(info.PluginApiVersions) > 0
}

Try / catch

if err := loader.Init(...); err != nil {
    if strings.Contains(err.Error(), "no compatible API versions") {
        // plugin forgot to declare versions; fix its PluginInfo
    }
}

Prevention

When it happens

Trigger: Plugin's PluginInfo() returns a PluginInfoResponse with PluginApiVersions set to nil or an empty slice.

Common situations: Custom internal plugin constructed the response without setting PluginApiVersions; plugin type template copied without filling the field.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/54e418aa1d70fd62. Report an issue: GitHub.

Appendix: source

Thrown at helper/pluginutils/loader/init.go:178

		fingerprinted[k] = info
	}

	if err := mErr.ErrorOrNil(); err != nil {
		return nil, err
	}

	return fingerprinted, nil
}

// selectApiVersion takes in PluginInfo and returns the highest compatable
// version or an error if the plugins response is malformed. If there is no
// overlap, an empty string is returned.
func (l *PluginLoader) selectApiVersion(i *base.PluginInfoResponse) (string, error) {
	if i == nil {
		return "", fmt.Errorf("nil plugin info given")
	}
	if len(i.PluginApiVersions) == 0 {
		return "", fmt.Errorf("plugin provided no compatible API versions")
	}

	pluginVersions, err := convertVersions(i.PluginApiVersions)
	if err != nil {
		return "", fmt.Errorf("plugin provided invalid versions: %v", err)
	}

	// Lookup the supported versions. These will be sorted highest to lowest
	supportedVersions, ok := l.supportedVersions[i.Type]
	if !ok {
		return "", fmt.Errorf("unsupported plugin type %q", i.Type)
	}

	for _, sv := range supportedVersions {
		for _, pv := range pluginVersions {
			if sv.Equal(pv) {
				return pv.Original(), nil
			}

View on GitHub (pinned to 482b49bf1a)