{"record":{"id":"715b133f8b99445a","repo":"hashicorp/nomad","slug":"node-secret-id-does-not-match-not-registering-nod","errorCode":null,"errorMessage":"node secret ID does not match. Not registering node.","messagePattern":"node secret ID does not match\\. Not registering node\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/node_endpoint.go","lineNumber":184,"sourceCode":"\tsnap, err := n.srv.fsm.State().Snapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tws := memdb.NewWatchSet()\n\toriginalNode, err := snap.NodeByID(ws, args.Node.ID)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// If the node has an entry in the state store, we perform a check to ensure\n\t// the secret ID matches the one stored. If there is no entry, we perform a\n\t// check to ensure the node is allowed to register given the request and the\n\t// server introduction enforcement configuration.\n\tif originalNode != nil {\n\t\t// Check if the SecretID has been tampered with\n\t\tif args.Node.SecretID != originalNode.SecretID && originalNode.SecretID != \"\" {\n\t\t\treturn fmt.Errorf(\"node secret ID does not match. Not registering node.\")\n\t\t}\n\n\t\t// Don't allow the Register method to update the node status. Only the\n\t\t// UpdateStatus method should be able to do this.\n\t\tif originalNode.Status != \"\" {\n\t\t\targs.Node.Status = originalNode.Status\n\t\t}\n\t\t// The called function performs all the required logging and metric\n\t\t// emitting, so we only need to check the return value.\n\t} else if !n.newRegistrationAllowed(args, authErr) {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\t// We have a valid node connection, so add the mapping to cache the\n\t// connection and allow the server to send RPCs to the client. We only cache\n\t// the connection if it is not being forwarded from another server.\n\tif n.ctx != nil && n.ctx.NodeID == \"\" && !args.IsForwarded() {\n\t\tn.ctx.NodeID = args.Node.ID","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/node_endpoint.go#L166-L202","documentation":"Nomad's node Register endpoint rejects registration when the SecretID sent in the request differs from the SecretID already stored for that node ID in state store. This guards against a node ID being hijacked or reused with different credentials. It is a server-side tamper/integrity check on node identity.","triggerScenarios":"Client calls Node.Register (RPC) with args.Node.SecretID different from the persisted node's SecretID while originalNode.SecretID is non-empty; node re-registers after a config change that regenerates its secret; two clients share the same node ID but different secrets.","commonSituations":"Operator copies a client config (including node ID) to a new machine without resetting state; client data dir wiped but node ID pinned, producing a new secret; stale server state after a restore; misconfigured `node_id` reuse across hosts.","solutions":["Ensure the client uses the same SecretID (from its secret file in the data dir) as the registered node — do not wipe the client's secret while keeping the same node ID","If the node is genuinely new/replaced, deregister the old node or change the client's node_id","Check for config duplication (same node_id on multiple clients) and assign unique node IDs","Restart the client with a fresh node_id so the server records a new node entry"],"exampleFix":"// before (client hcl): reused node id with fresh state\nnode {\n  id = \"abc-123\"\n}\n// after: let Nomad derive/keep the id and secret from the data dir\nnode {\n  # omit id, or keep the id AND preserve data/client/secret\n}","handlingStrategy":"validation","validationCode":"// before registering, compare with the server's stored node\nstored, _, err := client.Nodes().Info(nodeID, nil)\nif err == nil && stored != nil && stored.SecretID != \"\" && node.SecretID != stored.SecretID {\n    return fmt.Errorf(\"secret mismatch for node %s: regenerate node_id or restore original secret\", nodeID)\n}","typeGuard":"func secretMatches(stored, incoming string) bool {\n    return stored == \"\" || incoming == stored\n}","tryCatchPattern":"err := client.Nodes().Register(node, nil)\nif err != nil && strings.Contains(err.Error(), \"node secret ID does not match\") {\n    // stop retrying; requires manual reconciliation of node_id/secret\n}","preventionTips":["Never copy a client config with a fixed node_id to another host","Keep the client data dir (which holds the secret) intact across restarts","Assign unique node_ids per machine","Monitor for this error as a signal of node ID collisions"],"tags":["nomad","node-registration","security","secret-mismatch"],"backgroundTag":"node-secret-id-mismatch","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"}