{"record":{"id":"c317203a7af95169","repo":"hashicorp/nomad","slug":"plugin-s-doesn-t-implement-base-plugin-interface","errorCode":null,"errorMessage":"plugin %s doesn't implement base plugin interface","messagePattern":"plugin (.+?) doesn't implement base plugin interface","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/pluginutils/loader/loader.go","lineNumber":194,"sourceCode":"\t\tctx, cancel := context.WithCancel(context.Background())\n\t\tinstance = &internalPluginInstance{\n\t\t\tinstance:   pinfo.factory(ctx, logger),\n\t\t\tapiVersion: pinfo.apiVersion,\n\t\t\tkillFn:     cancel,\n\t\t}\n\t} else {\n\t\tvar err error\n\t\tinstance, err = l.dispensePlugin(pinfo.baseInfo.Type, pinfo.apiVersion, pinfo.exePath, pinfo.args, nil, logger)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to launch plugin: %v\", err)\n\t\t}\n\t}\n\n\t// Cast to the base type and set the config\n\tb, ok := instance.Plugin().(base.BasePlugin)\n\tif !ok {\n\t\tinstance.Kill() // Ensure plugin is not left running\n\t\treturn nil, fmt.Errorf(\"plugin %s doesn't implement base plugin interface\", id)\n\t}\n\n\tc := &base.Config{\n\t\tPluginConfig: pinfo.msgpackConfig,\n\t\tAgentConfig:  config,\n\t\tApiVersion:   pinfo.apiVersion,\n\t}\n\n\tif err := b.SetConfig(c); err != nil {\n\t\tinstance.Kill() // ensure plugin is not left running\n\t\treturn nil, fmt.Errorf(\"setting config for plugin %s failed: %v\", id, err)\n\t}\n\n\treturn instance, nil\n}\n\n// Reattach reattaches to a previously launched external plugin.\nfunc (l *PluginLoader) Reattach(name, pluginType string, config *plugin.ReattachConfig) (PluginInstance, error) {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/pluginutils/loader/loader.go#L176-L212","documentation":"After launching a plugin instance, Dispense casts instance.Plugin() to base.BasePlugin; if the cast fails the instance is killed and this error returned. The launched binary does not speak the required base plugin interface, so the loader cannot set config on it or use it.","triggerScenarios":"Dispense of a plugin whose dispensed PluginInstance does not implement base.BasePlugin — the binary serves a different plugin type/protocol, or a custom/incompatible go-plugin implementation returns a type not exposing the base plugin service.","commonSituations":"Pointing plugin_dir at a plugin built against an old Nomad plugin SDK without the base interface; mixing up binaries (a non-base plugin in the dir); hand-rolled go-plugin server that registers only a type-specific service without base.BasePlugin.","solutions":["Rebuild the plugin against the Nomad plugin SDK version matching the agent so it serves base.BasePlugin.","Confirm the binary is the intended plugin (correct name, correct plugin type registration).","Check the plugin's gRPC server registers the base plugin service, not only the driver/device service.","Verify API version compatibility between plugin and agent."],"exampleFix":"// before (plugin main.go)\nplugin.Serve(&plugin.ServeConfig{PluginFunc: func() interface{} { return &MyDriver{} }})\n// after (also serve/upgrade to the base plugin interface per current SDK)\nplugin.Serve(&plugin.ServeConfig{\n  PluginFunc: func() interface{} { return &MyDriver{} }, // ensure type implements base.BasePlugin\n})","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func asBasePlugin(inst loader.PluginInstance) (base.BasePlugin, bool) {\n    if inst == nil || inst.Plugin() == nil {\n        return nil, false\n    }\n    b, ok := inst.Plugin().(base.BasePlugin)\n    return b, ok\n}","tryCatchPattern":"inst, err := l.Dispense(name, ptype, agentCfg, logger)\nif err != nil && strings.Contains(err.Error(), \"doesn't implement base plugin interface\") {\n    return fmt.Errorf(\"plugin binary incompatible with agent SDK; rebuild against current nomad-sdk: %w\", err)\n}","preventionTips":["Build all external plugins against the Nomad plugin SDK version the agent expects","Ensure custom go-plugin servers implement and register base.BasePlugin","Verify plugin type registration matches the directory/type it's served under"],"tags":["plugin-loader","type-assertion","plugin-interface","nomad"],"backgroundTag":"plugin-interface-mismatch","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"}