{"record":{"id":"f932702605896199","repo":"hashicorp/nomad","slug":"missing-node-secret-id-for-client-registration","errorCode":null,"errorMessage":"missing node secret ID for client registration","messagePattern":"missing node secret ID for client registration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"nomad/structs/node.go","lineNumber":615,"sourceCode":"func (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 {\n\t\t\treturn fmt.Errorf(\"node is not allowed to register in node pool %q\", NodePoolAll)\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// ShouldGenerateNodeIdentity compliments the functionality within\n// AuthenticateNodeIdentityGenerator to determine whether a new node identity\n// should be generated within the RPC handler.\nfunc (n *NodeRegisterRequest) ShouldGenerateNodeIdentity(\n\tauthErr error,","sourceCodeStart":597,"sourceCodeEnd":633,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/node.go#L597-L633","documentation":"NodeRegisterRequest.Validate returns this error when Node.SecretID is empty. The secret ID is the node's per-node auth credential used to authenticate subsequent RPCs; registering without one would create a node that cannot authenticate, so it is mandatory.","triggerScenarios":"Calling Node.Register where Node.SecretID is the empty string — e.g. a client agent whose secret file in data_dir was deleted, or hand-built requests that set ID/DC/Name but skipped SecretID.","commonSituations":"Corrupted or wiped client data_dir losing node_secret_id; registration requests built by scripts/tools predating secret-ID enforcement (older Nomad versions used SecretID nil-able); testing fixtures copying only partial Node structs.","solutions":["Ensure the client agent generated its node secret (present in data_dir as the secret file); restart the agent to regenerate if missing, then re-register.","When constructing the request in code, generate and assign a secure random SecretID before Validate.","If migrating old tooling, update it to supply SecretID — legacy auth (node ID as secret) is no longer accepted."],"exampleFix":"// before\nnode := &structs.Node{ID: id, Datacenter: \"dc1\", Name: name, Attributes: attrs}\n// after\nnode := &structs.Node{ID: id, Datacenter: \"dc1\", Name: name, Attributes: attrs,\n\tSecretID: loadedOrGeneratedSecretID}","handlingStrategy":"validation","validationCode":"if node.SecretID == \"\" {\n\treturn errors.New(\"node SecretID is required; check data_dir secret file\")\n}","typeGuard":null,"tryCatchPattern":"if err := req.Validate(); err != nil {\n\tif strings.Contains(err.Error(), \"missing node secret ID\") {\n\t\treturn fmt.Errorf(\"regenerate node secret (restart client agent): %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Never wipe data_dir without preserving the node secret file.","Always generate a secure random SecretID when building registration requests programmatically.","Update legacy tooling that predates SecretID enforcement."],"tags":["nomad","rpc","validation","auth"],"backgroundTag":"missing-credentials","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"}