{"record":{"id":"bccbe7ada57fbbeb","repo":"hashicorp/nomad","slug":"failed-to-get-plugin-config-schema-for-plugin-q","errorCode":null,"errorMessage":"failed to get plugin config schema for plugin %q: %v","messagePattern":"failed to get plugin config schema for plugin %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/pluginutils/loader/init.go","lineNumber":401,"sourceCode":"\t\t\ti.Name, info.exePath, i.PluginVersion, err)\n\t}\n\tinfo.version = v\n\n\t// Detect the plugin API version to use\n\tav, err := l.selectApiVersion(i)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to validate API versions %v for plugin %s (%v): %v\", i.PluginApiVersions, i.Name, info.exePath, err)\n\t}\n\tif av == \"\" {\n\t\tl.logger.Warn(\"skipping plugin because supported API versions for plugin and Nomad do not overlap\", \"plugin\", i.Name, \"path\", info.exePath)\n\t\treturn nil, nil\n\t}\n\tinfo.apiVersion = av\n\n\t// Retrieve the schema\n\tschema, err := bplugin.ConfigSchema()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get plugin config schema for plugin %q: %v\", info.exePath, err)\n\t}\n\tinfo.configSchema = schema\n\n\treturn info, nil\n}\n\n// mergePlugins merges internal and external plugins, preferring the highest\n// version.\nfunc (l *PluginLoader) mergePlugins(internal, external map[PluginID]*pluginInfo) map[PluginID]*pluginInfo {\n\tfinalized := make(map[PluginID]*pluginInfo, len(internal))\n\n\t// Load the internal plugins\n\tfor k, v := range internal {\n\t\tfinalized[k] = v\n\t}\n\n\tfor k, extPlugin := range external {\n\t\tinternal, ok := finalized[k]","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/pluginutils/loader/init.go#L383-L419","documentation":"During plugin fingerprinting, the loader calls bplugin.ConfigSchema() on the launched external plugin to discover its configuration schema. If the plugin's gRPC ConfigSchema call fails (transport error, plugin crash, method not implemented for its API version, etc.), fingerprintPlugin wraps the underlying error with this message using the plugin's executable path. The plugin instance is discarded and the plugin fails to load.","triggerScenarios":"Calling loader.Init/getPluginLoader when an external plugin binary registers successfully but its BasePlugin.ConfigSchema() gRPC invocation returns an error, panics, or the plugin process dies mid-call during fingerprintPlugin.","commonSituations":"Plugin binary built against an incompatible go-plugin/base API version so ConfigSchema isn't supported; plugin crashes on startup before serving the RPC; mismatched Nomad/plugin dependency versions; binary lacks execute permissions or segfaults under load.","solutions":["Read the wrapped %v cause in the error message and fix the plugin's ConfigSchema implementation to return a valid schema or nil without error.","Verify the plugin binary is compatible with the host's supported plugin API versions (rebuild the plugin against the same sdk/base packages).","Run the plugin binary standalone to confirm it starts and serves gRPC without crashing (check permissions, missing shared libs, architecture).","Update the host (e.g. Nomad) or the plugin to matching versions so the API version negotiated (info.apiVersion) supports ConfigSchema."],"exampleFix":"// before (plugin-side, API v01 where ConfigSchema unsupported or errors)\nfunc (p *MyPlugin) ConfigSchema() (*hclspec.Spec, error) {\n    return nil, fmt.Errorf(\"not implemented\")\n}\n// after\nfunc (p *MyPlugin) ConfigSchema() (*hclspec.Spec, error) {\n    return hclspec.NewObject(map[string]*hclspec.Spec{\n        \"endpoint\": hclspec.NewAttr(\"endpoint\", \"string\", true),\n    }), nil\n}","handlingStrategy":"try-catch","validationCode":"// Before loading, sanity-check the plugin binary\ncmd := exec.Command(pluginPath, \"--help\")\nif err := cmd.Run(); err != nil {\n    return fmt.Errorf(\"plugin %s cannot start: %w\", pluginPath, err)\n}","typeGuard":"func hasConfigSchema(info *loader.PluginInfo) bool {\n    return info != nil && info.ConfigSchema != nil\n}","tryCatchPattern":"info, err := fingerprintPlugin(...)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to get plugin config schema\") {\n        log.Printf(\"plugin %s does not expose a config schema; check binary/API version\", pluginPath)\n        return nil // skip or fail loudly, with the inner cause logged\n    }\n    return err\n}","preventionTips":["Pin host and plugin to compatible versions (same base plugin API generation).","Smoke-test plugin binaries standalone before deploying them into plugin_dir.","Keep plugins executable with correct checksums and matching architecture.","Log the inner cause of schema errors, not just the wrapper."],"tags":["plugin-loader","grpc","config-schema","fingerprinting"],"backgroundTag":"plugin-rpc-config-schema-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"}