{"record":{"id":"feaf1dfb1b0d6362","repo":"hashicorp/nomad","slug":"either-id-or-address-must-be-set","errorCode":null,"errorMessage":"either ID or Address must be set","messagePattern":"either ID or Address must be set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/structs/operator.go","lineNumber":89,"sourceCode":"\tID raft.ServerID\n\n\t// WriteRequest holds the Region for this request.\n\tWriteRequest\n}\n\n// RaftPeerRequest is used by the Operator endpoint to apply a Raft\n// operation on a specific Raft peer by its peer ID or address in the form of\n// \"IP:port\".\ntype RaftPeerRequest struct {\n\t// RaftIDAddress contains an ID and Address field to identify the target\n\tRaftIDAddress\n\t// WriteRequest holds the Region for this request.\n\tWriteRequest\n}\n\nfunc (r *RaftPeerRequest) Validate() error {\n\tif (r.ID == \"\" && r.Address == \"\") || (r.ID != \"\" && r.Address != \"\") {\n\t\treturn errors.New(\"either ID or Address must be set\")\n\t}\n\tif r.ID != \"\" {\n\t\treturn r.validateID()\n\t}\n\treturn r.validateAddress()\n}\n\nfunc (r *RaftPeerRequest) validateID() error {\n\tif _, err := uuid.ParseUUID(string(r.ID)); err != nil {\n\t\treturn fmt.Errorf(\"id must be a uuid: %w\", err)\n\t}\n\treturn nil\n}\n\nfunc (r *RaftPeerRequest) validateAddress() error {\n\tif _, err := netip.ParseAddrPort(string(r.Address)); err != nil {\n\t\treturn fmt.Errorf(\"address must be in IP:port format: %w\", err)\n\t}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/structs/operator.go#L71-L107","documentation":"RaftPeerRequest.Validate requires exactly one of the peer ID or peer Address to be set; both empty or both set is invalid because the RPC cannot unambiguously identify the peer to operate on. It is used by operator raft transfer-leadership / peer-removal APIs.","triggerScenarios":"Calling OperatorRaftTransferLeadership or TransferLeadershipToPeer with a RaftPeerRequest where ID and Address are both empty, or both non-empty.","commonSituations":"Operator CLI/operator HTTP API calls to transfer Raft leadership without specifying -peer-id or -peer-address, or specifying both; programmatic clients building the request with leftover fields.","solutions":["Set exactly one of request.ID or request.Address","If both are known, pick ID (preferred) and clear Address","Fix the CLI/HTTP call to pass only one peer identifier"],"exampleFix":"// before\nreq := &structs.RaftPeerRequest{ID: \"abc-123\", Address: \"10.0.0.5:4647\"}\n// after\nreq := &structs.RaftPeerRequest{ID: \"abc-123\"}","handlingStrategy":"validation","validationCode":"if (req.ID == \"\" && req.Address == \"\") || (req.ID != \"\" && req.Address != \"\") {\n    return fmt.Errorf(\"set exactly one of RaftPeerRequest.ID or .Address\")\n}","typeGuard":"func hasOnePeerIdentifier(id, addr string) bool { return (id == \"\") != (addr == \"\") }","tryCatchPattern":"if err := req.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"either ID or Address\") {\n        // correct the request and retry once\n    }\n}","preventionTips":["Prefer peer ID over address when both are known","Build operator requests via helper constructors, not literals","Check CLI flags: pass -peer-id or -peer-address, never both"],"tags":["nomad","raft","operator-api","validation"],"backgroundTag":"invalid-request-parameter","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"}