{"record":{"id":"6d96ca43677af0ba","repo":"hashicorp/nomad","slug":"missing-node-id-for-client-registration","errorCode":null,"errorMessage":"missing node ID for client registration","messagePattern":"missing node ID for client registration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"nomad/structs/node.go","lineNumber":603,"sourceCode":"\tNode      *Node\n\tNodeEvent *NodeEvent\n\n\t// CreateNodePool is used to indicate that the node's node pool should be\n\t// created along with the node registration if it doesn't exist.\n\tCreateNodePool bool\n\n\tWriteRequest\n}\n\n// Validate checks that the NodeRegisterRequest is valid. Any returned error can\n// be sent back to the client as a response to the RPC call.\nfunc (n *NodeRegisterRequest) Validate() error {\n\n\tif n.Node == nil {\n\t\treturn errors.New(\"missing node for client registration\")\n\t}\n\tif n.Node.ID == \"\" {\n\t\treturn errors.New(\"missing node ID for client registration\")\n\t}\n\tif n.Node.Datacenter == \"\" {\n\t\treturn errors.New(\"missing datacenter for client registration\")\n\t}\n\tif n.Node.Name == \"\" {\n\t\treturn errors.New(\"missing node name for client registration\")\n\t}\n\tif len(n.Node.Attributes) == 0 {\n\t\treturn errors.New(\"missing attributes for client registration\")\n\t}\n\tif n.Node.SecretID == \"\" {\n\t\treturn errors.New(\"missing node secret ID for client registration\")\n\t}\n\tif n.Node.NodePool != \"\" {\n\t\tif err := ValidateNodePoolName(n.Node.NodePool); err != nil {\n\t\t\treturn fmt.Errorf(\"invalid node pool: %v\", err)\n\t\t}\n\t\tif n.Node.NodePool == NodePoolAll {","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/node.go#L585-L621","documentation":"NodeRegisterRequest.Validate returns this error when Node.ID is empty. The node ID is the unique identifier (usually a UUID) the server uses to track the client; without it the registration cannot proceed.","triggerScenarios":"Registering a node via Node.Register where the Node struct was created with an unset ID field, or where ID was set from an empty config value/environment variable.","commonSituations":"Newly provisioned clients whose node_id file was deleted or not yet generated; hand-crafted registration payloads in tests or migration scripts that omitted the ID; config templates where the ID placeholder wasn't rendered.","solutions":["Set Node.ID to the node's stable UUID before registering (Nomad clients generate and persist this in the data_dir).","If ID comes from config or environment, check for empty values and generate/persist one before registration.","Regenerate the client identity by restarting the Nomad agent so it writes a fresh node ID, then retry registration."],"exampleFix":"// before\nnode := &structs.Node{Datacenter: \"dc1\", Name: \"client-1\"}\n// after\nnode := &structs.Node{ID: generatedOrPersistedUUID, Datacenter: \"dc1\", Name: \"client-1\"}","handlingStrategy":"validation","validationCode":"if node.ID == \"\" {\n\treturn errors.New(\"node ID is required for registration\")\n}","typeGuard":null,"tryCatchPattern":"if err := req.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"missing node ID\") {\n\t\treturn fmt.Errorf(\"regenerate node identity (node ID missing): %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Persist the node UUID in data_dir and load it at startup.","Never build Node structs from potentially empty config values without checking.","Validate identity fields (ID, Datacenter, Name, SecretID) in one pre-flight pass."],"tags":["nomad","rpc","validation","missing-field"],"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"}