{"record":{"id":"7337c8ca5465bfb2","repo":"hashicorp/nomad","slug":"missing-node-id-for-client-status-update","errorCode":null,"errorMessage":"missing node ID for client status update","messagePattern":"missing node ID for client status update","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/node_endpoint.go","lineNumber":699,"sourceCode":"\tdefer metrics.MeasureSince([]string{\"nomad\", \"client\", \"update_status\"}, time.Now())\n\n\tif aclObj, err := n.srv.ResolveACL(args); err != nil {\n\t\treturn structs.ErrPermissionDenied\n\t} else {\n\t\tif aclObj.AllowServerOp() || args.GetIdentity().GetACLToken() == structs.LeaderACLToken {\n\t\t\tgoto VERIFY_ARGS\n\t\t}\n\n\t\tif err := auth.AuthorizeSameNode(args.GetIdentity(), args.NodeID); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\nVERIFY_ARGS:\n\n\t// Verify the arguments\n\tif args.NodeID == \"\" {\n\t\treturn fmt.Errorf(\"missing node ID for client status update\")\n\t}\n\tif !structs.ValidNodeStatus(args.Status) {\n\t\treturn fmt.Errorf(\"invalid status for node\")\n\t}\n\n\t// Look for the node\n\tsnap, err := n.srv.fsm.State().Snapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tws := memdb.NewWatchSet()\n\tnode, err := snap.NodeByID(ws, args.NodeID)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif node == nil {\n\t\treturn fmt.Errorf(\"node not found\")","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/node_endpoint.go#L681-L717","documentation":"Guard in Node.UpdateStatus: the heartbeat/status request has an empty NodeID, so the client status update has no target node; typically a misconfigured client identity.","triggerScenarios":"Client heartbeat/status RPC with NodeID empty — client started before its node ID was generated, or a wrapper built the request without copying NodeID.","commonSituations":"Custom clients/plugins implementing the heartbeat RPC incorrectly; config where node_id is templated but renders empty; proxy dropping fields.","solutions":["Ensure the client loads its generated node ID from the data dir before issuing UpdateStatus","Fix request construction to copy args.NodeID from the client's resolved identity","Regenerate the client data dir so a valid node ID is created","Check Nomad client logs for 'node ID' assignment errors at startup"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if args.NodeID == \"\" {\n    return fmt.Errorf(\"node ID must be resolved before UpdateStatus\")\n}","typeGuard":"func statusUpdatable(id, status string) bool {\n    return id != \"\"\n}","tryCatchPattern":"_, err := client.Nodes().UpdateStatus(nodeID, status, nil)\nif err != nil && strings.Contains(err.Error(), \"missing node ID\") {\n    // client identity not yet resolved: re-register or fix request builder\n}","preventionTips":["Ensure clients persist and reload their node ID from the data dir","Resolve node ID before any heartbeat RPCs","Validate request structs in wrapper libraries"],"tags":["nomad","validation","heartbeat","node-status"],"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"}