{"record":{"id":"37ea1cd7f5dc0db4","repo":"hashicorp/nomad","slug":"device-name-must-be-specified","errorCode":null,"errorMessage":"device name must be specified","messagePattern":"device name must be specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/device/device.go","lineNumber":98,"sourceCode":"\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}\n\n\tfor k, v := range d.Attributes {\n\t\tif err := v.Validate(); err != nil {\n\t\t\t_ = multierror.Append(&mErr, fmt.Errorf(\"device attribute %q invalid: %v\", k, err))\n\t\t}\n\t}","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/plugins/device/device.go#L80-L116","documentation":"Appended by DeviceGroup.Validate() when the group's Name is empty. Together with vendor and type, Name forms the unique device group identifier used in scheduling and resource accounting, so it must be non-empty.","triggerScenarios":"A DeviceGroup produced during fingerprinting has Name == \"\" when Validate() runs — e.g. the plugin did not derive a device group name from its config or detected hardware.","commonSituations":"Custom device plugin leaving Name unset; config key controlling the group name missing; renamed struct fields in a plugin update.","solutions":["Set DeviceGroup.Name in the plugin to a stable identifier for the group (e.g. \"k80\", \"a100\") and redeploy","Provide the missing group-name value in the plugin's client configuration","Validate the DeviceGroup in the plugin before returning it from Fingerprint so the error surfaces at plugin startup"],"exampleFix":"// before\n&device.DeviceGroup{Vendor: \"nvidia\", Type: device.DeviceTypeGPU}\n// after\n&device.DeviceGroup{Vendor: \"nvidia\", Type: device.DeviceTypeGPU, Name: \"a100\"}","handlingStrategy":"validation","validationCode":"// Go: guard before returning a DeviceGroup\nif g.Name == \"\" {\n    return nil, fmt.Errorf(\"device group %s/%s missing name\", g.Vendor, g.Type)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Derive Name from a stable, configured identifier for the device group","Validate DeviceGroup before publishing from Fingerprint","Include group name in plugin config schema so it cannot be silently omitted"],"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"}