{"record":{"id":"7725f5055ff3a625","repo":"hashicorp/nomad","slug":"unable-to-dispense-the-executor-plugin-v","errorCode":null,"errorMessage":"unable to dispense the executor plugin: %v","messagePattern":"unable to dispense the executor plugin: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/executor/utils.go","lineNumber":111,"sourceCode":"\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif _, err := exec.Version(); err != nil {\n\t\treturn nil, nil, err\n\t}\n\treturn exec, pluginClient, nil\n}\n\nfunc newExecutorClient(config *plugin.ClientConfig, logger hclog.Logger) (Executor, *plugin.Client, error) {\n\texecutorClient := plugin.NewClient(config)\n\trpcClient, err := executorClient.Client()\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"error creating rpc client for executor plugin: %v\", err)\n\t}\n\n\traw, err := rpcClient.Dispense(\"executor\")\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"unable to dispense the executor plugin: %v\", err)\n\t}\n\texecutorPlugin, ok := raw.(Executor)\n\tif !ok {\n\t\treturn nil, nil, fmt.Errorf(\"unexpected executor rpc type: %T\", raw)\n\t}\n\treturn executorPlugin, executorClient, nil\n}\n\nfunc processStateToProto(ps *ProcessState) (*proto.ProcessState, error) {\n\ttimestamp, err := ptypes.TimestampProto(ps.Time)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpb := &proto.ProcessState{\n\t\tPid:       int32(ps.Pid),\n\t\tExitCode:  int32(ps.ExitCode),\n\t\tSignal:    int32(ps.Signal),\n\t\tOomKilled: ps.OOMKilled,","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/executor/utils.go#L93-L129","documentation":"Returned when the go-plugin RPC connection succeeded but rpcClient.Dispense(\"executor\") failed to produce the named plugin. go-plugin Dispense errors when the requested plugin name is not in the plugin set the client was configured with, meaning the PluginSet catalog in the ClientConfig does not contain an entry named \"executor\" (or the broker failed to dispense that plugin stub).","triggerScenarios":"newExecutorClient builds a plugin.ClientConfig whose Plugins map lacks the \"executor\" key, or the plugin set version negotiated differs so the name is absent; can occur in both CreateExecutor and ReattachToExecutor paths.","commonSituations":"Code changes renaming/omitting the executor entry in the plugin set; a custom build linking a different plugin catalog; version skew between the launcher that wrote the reattach config and the reattaching binary.","solutions":["Confirm the plugin.ClientConfig.Plugins map passed to newExecutorClient contains key \"executor\" mapped to the ExecutorPlugin implementation","Ensure launcher and reattacher are the same Nomad version so the plugin set matches","Rebuild/redeploy the client binary — a stale or partially upgraded install can ship a mismatched catalog","If wrapping go-plugin directly, add plugins: map[string]plugin.Plugin{\"executor\": &ExecutorPlugin{}} to the config"],"exampleFix":"// before\nconfig := &plugin.ClientConfig{HandshakeConfig: handshake, VersionedPlugins: versionedPlugins}\n// after: ensure the executor plugin is registered for the negotiated version\nconfig := &plugin.ClientConfig{\n    HandshakeConfig: handshake,\n    VersionedPlugins: map[int]plugin.PluginSet{\n        1: {\"executor\": &ExecutorPlugin{}},\n    },\n}","handlingStrategy":"type-guard","validationCode":"// ensure the client config registers the executor plugin before creating the client\nif _, ok := config.Plugins[\"executor\"]; !ok {\n    return fmt.Errorf(\"executor plugin not registered in plugin set\")\n}","typeGuard":"func isExecutorRegistered(cfg *plugin.ClientConfig) bool {\n    for _, set := range cfg.VersionedPlugins {\n        if _, ok := set[\"executor\"]; ok { return true }\n    }\n    if _, ok := cfg.Plugins[\"executor\"]; ok { return true }\n    return false\n}","tryCatchPattern":"raw, err := rpcClient.Dispense(\"executor\")\nif err != nil {\n    return fmt.Errorf(\"dispense executor: %w\", err) // inspect: plugin set mismatch, not transient\n}","preventionTips":["Always register {\"executor\": &ExecutorPlugin{}} in the plugin set for every negotiated version","Use build-time tests that Dispense(\"executor\") succeeds against the shipped catalog","Keep launcher and reattach code paths on the same binary version"],"tags":["go-plugin","rpc","plugin-dispense","nomad"],"backgroundTag":"plugin-dispense-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"}