{"record":{"id":"c3b8eeb98bde4318","repo":"hashicorp/nomad","slug":"missing-nodeid","errorCode":null,"errorMessage":"missing NodeID","messagePattern":"missing NodeID","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/client_alloc_endpoint.go","lineNumber":66,"sourceCode":"\tif done, err := a.srv.forward(\"ClientAllocations.GarbageCollectAll\", args, args, reply); done {\n\t\treturn err\n\t}\n\ta.srv.MeasureRPCRate(\"client_allocations\", structs.RateMetricWrite, args)\n\tif authErr != nil {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"client_allocations\", \"garbage_collect_all\"}, time.Now())\n\n\t// Check node read permissions\n\tif aclObj, err := a.srv.ResolveACL(args); err != nil {\n\t\treturn err\n\t} else if !aclObj.AllowNodeWrite() {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\n\t// Verify the arguments.\n\tif args.NodeID == \"\" {\n\t\treturn errors.New(\"missing NodeID\")\n\t}\n\n\t// Make sure Node is valid and new enough to support RPC\n\tsnap, err := a.srv.State().Snapshot()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t_, err = getNodeForRpc(snap, args.NodeID)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// Get the connection to the client\n\tstate, ok := a.srv.getNodeConn(args.NodeID)\n\tif !ok {\n\t\treturn findNodeConnAndForward(a.srv, args.NodeID, \"ClientAllocations.GarbageCollectAll\", args, reply)\n\t}","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/client_alloc_endpoint.go#L48-L84","documentation":"The GarbageCollectAll RPC on nomad/client_alloc_endpoint.go validates args.NodeID before forwarding the request to the client. This error is returned when the NodeID field of the NodeSpecificRequest is the empty string, meaning the caller never specified which node's allocations to garbage collect. It is a client-side argument validation failure, thrown before any state lookup or RPC forwarding happens.","triggerScenarios":"Calling ClientAllocations.GarbageCollectAll with a structs.NodeSpecificRequest whose NodeID field is \"\" (zero value left unset).","commonSituations":"Constructing the request struct without setting NodeID; using a node object whose ID field was empty (e.g. node not yet registered, or a zero-valued struct passed in); a wrapper/CLI that fails to resolve a node name to a NodeID.","solutions":["Set args.NodeID to the target node's 36-character UUID before invoking GarbageCollectAll.","Resolve the node by name via the Node List API and copy its ID into the request.","Validate NodeID != \"\" in your calling code before making the RPC."],"exampleFix":"// before\nargs := structs.NodeSpecificRequest{}\nerr := client.GarbageCollectAll(args, &structs.GenericResponse{})\n// after\nargs := structs.NodeSpecificRequest{NodeID: node.ID}\nerr := client.GarbageCollectAll(args, &structs.GenericResponse{})","handlingStrategy":"validation","validationCode":"if node == nil || node.ID == \"\" {\n    return fmt.Errorf(\"cannot GC all allocations: NodeID is empty; resolve node first\")\n}","typeGuard":"func hasNodeID(args *structs.NodeSpecificRequest) bool {\n    return args != nil && args.NodeID != \"\"\n}","tryCatchPattern":null,"preventionTips":["Always construct NodeSpecificRequest with an explicit NodeID from a resolved node object.","Resolve node names to IDs via the nodes list API before RPC calls.","Fail fast with your own validation error rather than an empty-ID RPC."],"tags":["nomad","rpc","argument-validation","node"],"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"}