{"record":{"id":"dc1fd382ea58897d","repo":"hashicorp/nomad","slug":"device-vendor-must-be-specified","errorCode":null,"errorMessage":"device vendor must be specified","messagePattern":"device vendor must be specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/device/device.go","lineNumber":92,"sourceCode":"\t// Type is the type of the device (gpu, fpga, etc).\n\tType string\n\n\t// Name is the devices model name.\n\tName string\n\n\t// Devices is the set of device instances.\n\tDevices []*Device\n\n\t// Attributes are a set of attributes shared for all the devices.\n\tAttributes map[string]*structs.Attribute\n}\n\n// Validate validates that the device group is valid\nfunc (d *DeviceGroup) Validate() error {\n\tvar mErr multierror.Error\n\n\tif d.Vendor == \"\" {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"device vendor must be specified\"))\n\t}\n\tif d.Type == \"\" {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"device type must be specified\"))\n\t}\n\tif d.Name == \"\" {\n\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"device name must be specified\"))\n\t}\n\n\tfor i, dev := range d.Devices {\n\t\tif dev == nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"device %d is nil\", i))\n\t\t\tcontinue\n\t\t}\n\n\t\tif err := dev.Validate(); err != nil {\n\t\t\t_ = multierror.Append(&mErr, multierror.Prefix(err, fmt.Sprintf(\"device %d: \", i)))\n\t\t}\n\t}","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/plugins/device/device.go#L74-L110","documentation":"DeviceGroup.Validate() builds a multierror of required fields; this entry is appended when the device group's Vendor field is empty. Device groups in Nomad must be namespaced by vendor, type, and name, so a missing vendor makes the group identity invalid.","triggerScenarios":"A device plugin's fingerprint/DeviceGroup struct returned with Vendor == \"\" and passed to Validate() — typically a mis-implemented or misconfigured device plugin.","commonSituations":"Custom/first-party device plugin whose config lacks a vendor identifier; plugin author returning a DeviceGroup literal without setting Vendor; test fixtures omitting the field.","solutions":["Set the Vendor field on the DeviceGroup in the plugin (e.g. \"nvidia\", \"usb\") and redeploy the plugin","If configuring the plugin, supply the vendor value in the plugin's client config so fingerprinting populates it","Add a unit test / validate call around DeviceGroup construction to catch empty fields before fingerprinting"],"exampleFix":"// before\nreturn &device.DeviceGroup{Type: device.DeviceTypeGPU, Name: \"k80\"}, nil\n// after\nreturn &device.DeviceGroup{Vendor: \"nvidia\", Type: device.DeviceTypeGPU, Name: \"k80\"}, nil","handlingStrategy":"validation","validationCode":"// Go: guard before returning a DeviceGroup\nif g.Vendor == \"\" {\n    return nil, fmt.Errorf(\"device group %q missing vendor\", g.Name)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set Vendor from plugin config constants when constructing DeviceGroup","Call DeviceGroup.Validate() inside the plugin before publishing fingerprint results","Add unit tests asserting vendor/type/name are populated"],"tags":["devices","validation","plugin"],"backgroundTag":"missing-required-argument","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"}