{"record":{"id":"229d6383eb22ecf3","repo":"hashicorp/nomad","slug":"must-provide-peer-id-or-address","errorCode":null,"errorMessage":"must provide peer id or address","messagePattern":"must provide peer id or address","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"nomad/operator_endpoint.go","lineNumber":257,"sourceCode":"\t// TransferLeadership is not supported until Raft protocol v3 or greater.\n\tif minRaftProtocol < 3 {\n\t\top.logger.Warn(\"unsupported minimum common raft protocol version\", \"required\", \"3\", \"current\", minRaftProtocol)\n\t\treply.Err = errors.New(\"unsupported minimum common raft protocol version\")\n\t\treturn structs.NewErrRPCCoded(http.StatusBadRequest, reply.Err.Error())\n\t}\n\n\tvar kind, testedVal string\n\n\t// The request must provide either an ID or an Address, this lets us validate\n\t// the request\n\treq.Validate()\n\tswitch {\n\tcase req.ID != \"\":\n\t\tkind, testedVal = \"id\", string(req.ID)\n\tcase req.Address != \"\":\n\t\tkind, testedVal = \"address\", string(req.Address)\n\tdefault:\n\t\treply.Err = errors.New(\"must provide peer id or address\")\n\t\treturn structs.NewErrRPCCoded(http.StatusBadRequest, reply.Err.Error())\n\t}\n\n\t// Get the raft configuration\n\tfuture := op.srv.raft.GetConfiguration()\n\tif err := future.Error(); err != nil {\n\t\treply.Err = err\n\t\treturn err\n\t}\n\n\t// Since this is an operation designed for humans to use, we will return\n\t// an error if the supplied ID or address isn't among the peers since it's\n\t// likely a mistake.\n\tvar found bool\n\tfor _, s := range future.Configuration().Servers {\n\t\tif s.ID == req.ID || s.Address == req.Address {\n\t\t\treply.To = structs.NewRaftIDAddress(s.Address, s.ID)\n\t\t\tfound = true","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/operator_endpoint.go#L239-L275","documentation":"TransferLeadershipToPeer requires the request to identify the target peer by either ID or Address; the switch falls to the default case when both are empty and returns a 400. This is input validation to avoid transferring leadership to an unspecified peer.","triggerScenarios":"Calling `nomad operator raft transfer-leadership` or POST /v1/operator/raft/transfer-leadership with a JSON body lacking both id and address fields (e.g. `{}`), or using a client/API wrapper that drops the peer parameter.","commonSituations":"Hand-crafted HTTP requests against the operator API; older CLI against newer API or vice versa; automation scripts building the payload programmatically with empty variables.","solutions":["Pass -peer-id <uuid> or -peer-address <ip:port> to the CLI command","Include either \"id\" or \"address\" in the request body of the HTTP call","Look up a valid peer id first via `nomad operator raft list-peers`"],"exampleFix":"// before\nnomad operator raft transfer-leadership\n// after\nnomad operator raft transfer-leadership -peer-id 1b6088cd-1f6e-4d3e-9f7f-4b0f8e2a1234","handlingStrategy":"validation","validationCode":"func validateTransferReq(req *structs.TransferLeaderRequest) error {\n    if req.ID == \"\" && req.Address == \"\" {\n        return errors.New(\"must supply -peer-id or -peer-address\")\n    }\n    return nil\n}","typeGuard":"func hasPeerTarget(id, address string) bool {\n    return id != \"\" || address != \"\"\n}","tryCatchPattern":"if err := transferLeadership(id, addr); err != nil {\n    if strings.Contains(err.Error(), \"must provide peer id or address\") {\n        return fmt.Errorf(\"supply peer target: %w\", err)\n    }\n    return err\n}","preventionTips":["Run `nomad operator raft list-peers` to capture a valid id before transferring","Never build transfer payloads with unbound/empty template variables","Validate CLI flags non-empty before issuing the RPC"],"tags":["nomad","raft","api-validation","leader-election"],"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"}