{"record":{"id":"5f43e2925e52804b","repo":"hashicorp/nomad","slug":"must-specify-plugin-type-to-dispense","errorCode":null,"errorMessage":"must specify plugin type to dispense","messagePattern":"must specify plugin type to dispense","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/dynamicplugins/registry.go","lineNumber":374,"sourceCode":"\n\t\tif delay < maxDelay {\n\t\t\tdelay += delay\n\t\t}\n\t\tif delay > maxDelay {\n\t\t\tdelay = maxDelay\n\t\t}\n\t\ttimer.Reset(time.Duration(delay) * time.Millisecond)\n\t}\n}\n\nfunc (d *dynamicRegistry) DispensePlugin(ptype string, name string) (any, error) {\n\td.pluginsLock.Lock()\n\tdefer d.pluginsLock.Unlock()\n\n\tif ptype == \"\" {\n\t\t// This error shouldn't make it to a production cluster and is to aid\n\t\t// developers during the development of new plugin types.\n\t\treturn nil, errors.New(\"must specify plugin type to dispense\")\n\t}\n\tif name == \"\" {\n\t\t// This error shouldn't make it to a production cluster and is to aid\n\t\t// developers during the development of new plugin types.\n\t\treturn nil, errors.New(\"must specify plugin name to dispense\")\n\t}\n\n\tdispenseFunc, ok := d.dispensers[ptype]\n\tif !ok {\n\t\t// This error shouldn't make it to a production cluster and is to aid\n\t\t// developers during the development of new plugin types.\n\t\treturn nil, fmt.Errorf(\"no plugin dispenser found for type: %s\", ptype)\n\t}\n\n\t// After initially loading the dispenser (to avoid masking missing setup in\n\t// client/client.go), we then check to see if we have any stub dispensers for\n\t// this plugin type. If we do, then replace the dispenser fn with the stub.\n\tif d.stubDispensers != nil {","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/dynamicplugins/registry.go#L356-L392","documentation":"DispensePlugin looks up a registered dispenser function by plugin type. An empty type cannot match any registered dispenser, so the registry immediately returns this developer-aid error before any lookup.","triggerScenarios":"Calling Registry.DispensePlugin(ptype, name) with ptype == \"\", e.g. a volume/driver manager that obtains the plugin type from a request field that is empty.","commonSituations":"CSI volume mount/unmount workflows where the driver's plugin type was not resolved, or code passing an empty string after a failed type inference.","solutions":["Pass the correct plugin type constant (e.g. dynamicplugins.PluginTypeCSIDriver or PluginTypeCSINode)","Validate ptype is non-empty before dispensing","Check the upstream struct/request field that supplies the type and fix why it is empty"],"exampleFix":"// before\nplugin, err := registry.DispensePlugin(\"\", pluginName)\n// after\nif ptype == \"\" {\n    return nil, fmt.Errorf(\"cannot dispense plugin %q: plugin type is empty\", pluginName)\n}\nplugin, err := registry.DispensePlugin(ptype, pluginName)","handlingStrategy":"validation","validationCode":"if ptype == \"\" {\n    return fmt.Errorf(\"dispense: plugin type is required\")\n}\nplugin, err := registry.DispensePlugin(ptype, name)","typeGuard":"func canDispense(ptype, name string) bool {\n    return ptype != \"\" && name != \"\"\n}","tryCatchPattern":"plugin, err := registry.DispensePlugin(ptype, name)\nif err != nil {\n    if strings.Contains(err.Error(), \"must specify plugin type\") {\n        return fmt.Errorf(\"dispense failed: unknown/empty plugin type %q: %w\", ptype, err)\n    }\n    return err\n}","preventionTips":["Pass dynamicplugins.PluginType* constants, never user-supplied raw strings","Resolve plugin type from the registered plugin info, not from optional request fields","Add assertions that dispenser lookup inputs are non-empty"],"tags":["validation","plugin-registry","nomad"],"backgroundTag":"empty-required-field","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"}