{"record":{"id":"88175bf5579a35f2","repo":"hashicorp/nomad","slug":"device-name-must-be-given-as-one-of-the-following","errorCode":null,"errorMessage":"device name must be given as one of the following: type, vendor/type, or vendor/type/name","messagePattern":"device name must be given as one of the following: type, vendor/type, or vendor/type/name","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/structs.go","lineNumber":3132,"sourceCode":"\t\t\tType:   parts[1],\n\t\t}\n\tdefault:\n\t\treturn &DeviceIdTuple{\n\t\t\tVendor: parts[0],\n\t\t\tType:   parts[1],\n\t\t\tName:   parts[2],\n\t\t}\n\t}\n}\n\nfunc (r *RequestedDevice) Validate() error {\n\tif r == nil {\n\t\treturn nil\n\t}\n\n\tvar mErr multierror.Error\n\tif r.Name == \"\" {\n\t\t_ = multierror.Append(&mErr, errors.New(\"device name must be given as one of the following: type, vendor/type, or vendor/type/name\"))\n\t}\n\n\tfor idx, constr := range r.Constraints {\n\t\t// Ensure that the constraint doesn't use an operand we do not allow\n\t\tswitch constr.Operand {\n\t\tcase ConstraintDistinctHosts, ConstraintDistinctProperty:\n\t\t\touter := fmt.Errorf(\"Constraint %d validation failed: using unsupported operand %q\", idx+1, constr.Operand)\n\t\t\t_ = multierror.Append(&mErr, outer)\n\t\tdefault:\n\t\t\tif err := constr.Validate(); err != nil {\n\t\t\t\touter := fmt.Errorf(\"Constraint %d validation failed: %s\", idx+1, err)\n\t\t\t\t_ = multierror.Append(&mErr, outer)\n\t\t\t}\n\t\t}\n\t}\n\tfor idx, affinity := range r.Affinities {\n\t\tif err := affinity.Validate(); err != nil {\n\t\t\touter := fmt.Errorf(\"Affinity %d validation failed: %s\", idx+1, err)","sourceCodeStart":3114,"sourceCodeEnd":3150,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/structs.go#L3114-L3150","documentation":"DeviceRequest.Validate requires a non-empty Name formatted as type, vendor/type, or vendor/type/name (Consul/Nomad device plugin namespace convention, e.g. \"gpu\", \"nvidia/gpu\", \"nvidia/gpu/gtx1080\"). An empty or malformed device name fails validation.","triggerScenarios":"A resources { devices {} } block (DeviceRequest) whose name field is empty or does not follow the type[/vendor[/name]] shape when the job is validated.","commonSituations":"Omitting name when declaring device requests; typos like \"nvidia\" vendor-only paths are fine but empty strings are not; templating that leaves name blank.","solutions":["Set the device name following the allowed formats, e.g. name = \"gpu\" or name = \"nvidia/gpu\"","Match the name to what the device plugin exposes (vendor/type from plugin fingerprints)"],"exampleFix":"// before\ndevices {\n  name = \"\"\n}\n// after\ndevices {\n  name = \"nvidia/gpu\"\n}","handlingStrategy":"validation","validationCode":"const DEVICE_NAME_RE = /^[a-z0-9-]+(\\/[a-z0-9-]+)?(\\/[a-z0-9-]+)?$/i;\nfunction validateDeviceName(dev) {\n  if (!DEVICE_NAME_RE.test(dev.name ?? \"\")) {\n    throw new Error(`device name must be type, vendor/type, or vendor/type/name; got \"${dev.name}\"`);\n  }\n}","typeGuard":"function hasValidDeviceName(d) { return typeof d.name === \"string\" && d.name.split(\"/\").length <= 3 && d.name.length > 0; }","tryCatchPattern":"try {\n  await nomad.jobs.validate(job);\n} catch (e) {\n  if (e.message.includes(\"device name must be given\")) {\n    console.error(\"Set device name like 'gpu', 'nvidia/gpu', or 'nvidia/gpu/gtx1080'\");\n  } else throw e;\n}","preventionTips":["Match device names to the device plugin's vendor/type identifiers","Require explicit device name in templates (no silent defaults)","Verify names against nomad node status device fingerprint output"],"tags":["nomad","devices","gpu","job-validation"],"backgroundTag":"invalid-identifier-format","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"}