{"record":{"id":"735e4cc05e623107","repo":"hashicorp/nomad","slug":"failed-to-dispense-plugin-v","errorCode":null,"errorMessage":"failed to dispense plugin: %v","messagePattern":"failed to dispense plugin: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"helper/pluginutils/loader/init.go","lineNumber":510,"sourceCode":"\tif diag.HasErrors() {\n\t\t_ = multierror.Append(&mErr, diagErrs...)\n\t\treturn nil, multierror.Prefix(&mErr, \"failed to parse config: \")\n\n\t}\n\n\t// Marshal the value\n\tcdata, err := msgpack.Marshal(val, val.Type())\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to msgpack encode config: %v\", err)\n\t}\n\n\t// Store the marshalled config\n\tinfo.msgpackConfig = cdata\n\n\t// Dispense the plugin and set its config and ensure it is error free\n\tinstance, err := l.Dispense(id.Name, id.PluginType, nil, l.logger)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to dispense plugin: %v\", err)\n\t}\n\tdefer instance.Kill()\n\n\tb, ok := instance.Plugin().(base.BasePlugin)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"dispensed plugin %s doesn't meet base plugin interface\", id)\n\t}\n\n\tc := &base.Config{\n\t\tPluginConfig: cdata,\n\t\tAgentConfig:  nil,\n\t\tApiVersion:   info.apiVersion,\n\t}\n\n\tif err := b.SetConfig(c); err != nil {\n\t\treturn nil, fmt.Errorf(\"setting config on plugin failed: %v\", err)\n\t}\n","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/helper/pluginutils/loader/init.go#L492-L528","documentation":"To validate the config end-to-end, validatePluginConfig dispenses a throwaway instance of the plugin via l.Dispense(name, pluginType, nil, logger). Any error from Dispense — failure to launch the plugin binary, handshake failure, or the requested name/type not being registered — is wrapped as \"failed to dispense plugin\". The instance is killed immediately after validation.","triggerScenarios":"validatePluginConfig calls l.Dispense(id.Name, id.PluginType, nil, l.logger) and Dispense returns an error: plugin binary can't be launched (bad path/permissions), go-plugin handshake/autoclibsys fails, or no plugin factory is registered for the (name, type) pair.","commonSituations":"Plugin binary deleted/moved or not executable after registration; plugin crashes during handshake (missing libs, wrong architecture, seccomp restricting forks); plugin ID mismatch between fingerprinting and dispense; resource limits preventing process spawn.","solutions":["Check the wrapped %v cause: if it's a launch/exec error, verify the plugin's exe path exists and is executable and that its checksum matches config.","Run the plugin binary directly to see startup errors (missing shared libraries, wrong arch, crash on init).","Ensure the plugin is still registered in the loader catalog (name + pluginType match what was registered at load time).","Check host environment for process-spawn restrictions (seccomp, cgroup limits, TMPDIR writability for go-plugin sockets).","Update/re-download the plugin to a build compatible with the host version."],"exampleFix":"// before (agent config pointing at missing binary)\nplugin_dir = \"/opt/nomad-plugins\"  # my-plugin binary absent\n// after\nplugin_dir = \"/opt/nomad-plugins\"  # with my-plugin present & chmod +x, checksum verified","handlingStrategy":"try-catch","validationCode":"// Ensure the binary exists, is executable, and checksum matches before load\nst, err := os.Stat(pluginPath)\nif err != nil || st.IsDir() || st.Mode()&0111 == 0 {\n    return fmt.Errorf(\"plugin binary %s missing or not executable\", pluginPath)\n}\nif want, got := expectedChecksum, shaFile(pluginPath); want != got {\n    return fmt.Errorf(\"plugin checksum mismatch: want %s got %s\", want, got)\n}","typeGuard":null,"tryCatchPattern":"if err := loader.Load(cfg); err != nil {\n    if strings.Contains(err.Error(), \"failed to dispense plugin\") {\n        log.Printf(\"plugin %s could not be launched; verify binary, permissions, and handshake: %v\", name, err)\n        return err\n    }\n    return err\n}","preventionTips":["Verify plugin binary presence, exec bit, and checksums as a pre-flight step.","Run the plugin binary manually to catch missing libraries/arch mismatches early.","Avoid restrictive seccomp/TMPDIR setups that break go-plugin Unix sockets.","Keep plugin_dir contents aligned with configured plugin stanzas."],"tags":["plugin-loader","plugin-dispense","process-launch","grpc-handshake"],"backgroundTag":"plugin-launch-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"}