{"record":{"id":"064af34bc962e0f3","repo":"hashicorp/nomad","slug":"failed-to-validate-api-versions-v-for-internal-pl","errorCode":null,"errorMessage":"failed to validate API versions %v for internal plugin %s: %v","messagePattern":"failed to validate API versions (.+?) for internal plugin (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/pluginutils/loader/init.go","lineNumber":142,"sourceCode":"\t\ti, err := base.PluginInfo()\n\t\tif err != nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"PluginInfo info failed for internal plugin %s: %v\", k, err))\n\t\t\tcontinue\n\t\t}\n\t\tinfo.baseInfo = i\n\n\t\t// Parse and set the plugin version\n\t\tv, err := version.NewVersion(i.PluginVersion)\n\t\tif err != nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"failed to parse version %q for internal plugin %s: %v\", i.PluginVersion, k, err))\n\t\t\tcontinue\n\t\t}\n\t\tinfo.version = v\n\n\t\t// Detect the plugin API version to use\n\t\tav, err := l.selectApiVersion(i)\n\t\tif err != nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"failed to validate API versions %v for internal plugin %s: %v\", i.PluginApiVersions, k, err))\n\t\t\tcontinue\n\t\t}\n\t\tif av == \"\" {\n\t\t\tl.logger.Warn(\"skipping plugin because supported API versions for plugin and Nomad do not overlap\", \"plugin\", k)\n\t\t\tcontinue\n\t\t}\n\t\tinfo.apiVersion = av\n\n\t\t// Get the config schema\n\t\tschema, err := base.ConfigSchema()\n\t\tif err != nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"failed to retrieve config schema for internal plugin %s: %v\", k, err))\n\t\t\tcontinue\n\t\t}\n\t\tinfo.configSchema = schema\n\n\t\t// Store the fingerprinted config\n\t\tfingerprinted[k] = info","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/pluginutils/loader/init.go#L124-L160","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Upgrade Nomad (or the plugin) so the plugin's API versions overlap with the loader's supported versions for its type","Verify the plugin's PluginInfoResponse.Type is a supported type (e.g. base.PluginTypeCSI) and PluginApiVersions is non-empty with valid versions","Read the inner %v error to distinguish empty/invalid versions vs unsupported type"],"exampleFix":"// before\n&base.PluginInfoResponse{Type: \"storage\", PluginApiVersions: nil}\n// after\n&base.PluginInfoResponse{Type: base.PluginTypeCSI, PluginApiVersions: []string{\"v1\"}}","handlingStrategy":"validation","validationCode":"resp, err := p.PluginInfo()\nif err != nil || resp == nil || len(resp.PluginApiVersions) == 0 {\n    return fmt.Errorf(\"plugin must declare PluginApiVersions\")\n}\nif _, ok := supportedVersions[resp.Type]; !ok {\n    return fmt.Errorf(\"unsupported plugin type %q\", resp.Type)\n}","typeGuard":"func negotiable(info *base.PluginInfoResponse, supported map[string][]string) bool {\n    return info != nil && info.Type != \"\" && len(info.PluginApiVersions) > 0 && supported[info.Type] != nil\n}","tryCatchPattern":"if err := loader.Init(...); err != nil {\n    if strings.Contains(err.Error(), \"failed to validate API versions\") {\n        // compare plugin's PluginApiVersions with Nomad's supported versions\n    }\n}","preventionTips":["Pin plugin API versions to constants shared between plugin and host","Upgrade Nomad and plugins together when API versions change","Log both version lists when negotiation fails to make overlap gaps obvious"],"tags":["go","plugin-loader","api-version-negotiation","nomad"],"backgroundTag":"api-version-negotiation-failed","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}