hashicorp/nomad · error

failed to validate API versions %v for internal plugin %s: %

Error message

failed to validate API versions %v for internal plugin %s: %v

What it means

selectApiVersion negotiates the highest API version shared between the plugin's PluginApiVersions and the loader's supportedVersions for the plugin type. If it returns an error (no versions listed, invalid versions, or unsupported plugin type), initInternal wraps it with this message and skips the plugin.

Source

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

		i, err := base.PluginInfo()
		if err != nil {
			_ = multierror.Append(&mErr, fmt.Errorf("PluginInfo info failed for internal plugin %s: %v", k, err))
			continue
		}
		info.baseInfo = i

		// Parse and set the plugin version
		v, err := version.NewVersion(i.PluginVersion)
		if err != nil {
			_ = multierror.Append(&mErr, fmt.Errorf("failed to parse version %q for internal plugin %s: %v", i.PluginVersion, k, err))
			continue
		}
		info.version = v

		// Detect the plugin API version to use
		av, err := l.selectApiVersion(i)
		if err != nil {
			_ = multierror.Append(&mErr, fmt.Errorf("failed to validate API versions %v for internal plugin %s: %v", i.PluginApiVersions, k, err))
			continue
		}
		if av == "" {
			l.logger.Warn("skipping plugin because supported API versions for plugin and Nomad do not overlap", "plugin", k)
			continue
		}
		info.apiVersion = av

		// Get the config schema
		schema, err := base.ConfigSchema()
		if err != nil {
			_ = multierror.Append(&mErr, fmt.Errorf("failed to retrieve config schema for internal plugin %s: %v", k, err))
			continue
		}
		info.configSchema = schema

		// Store the fingerprinted config
		fingerprinted[k] = info

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Upgrade Nomad (or the plugin) so the plugin's API versions overlap with the loader's supported versions for its type
  2. Verify the plugin's PluginInfoResponse.Type is a supported type (e.g. base.PluginTypeCSI) and PluginApiVersions is non-empty with valid versions
  3. Read the inner %v error to distinguish empty/invalid versions vs unsupported type

Example fix

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

Strategy: validation

Validate before calling

resp, err := p.PluginInfo()
if err != nil || resp == nil || len(resp.PluginApiVersions) == 0 {
    return fmt.Errorf("plugin must declare PluginApiVersions")
}
if _, ok := supportedVersions[resp.Type]; !ok {
    return fmt.Errorf("unsupported plugin type %q", resp.Type)
}

Type guard

func negotiable(info *base.PluginInfoResponse, supported map[string][]string) bool {
    return info != nil && info.Type != "" && len(info.PluginApiVersions) > 0 && supported[info.Type] != nil
}

Try / catch

if err := loader.Init(...); err != nil {
    if strings.Contains(err.Error(), "failed to validate API versions") {
        // compare plugin's PluginApiVersions with Nomad's supported versions
    }
}

Prevention

When it happens

Trigger: initInternal calls l.selectApiVersion(i) and it errors because: PluginApiVersions is empty, contains unparsable strings, i.Type is not a registered/supported plugin type, or the version lists are malformed.

Common situations: Plugin built against an API the Nomad version doesn't support; plugin reports type "" or a custom type Nomad has no supported versions table for; plugin forgot to declare PluginApiVersions.

Related errors


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