hashicorp/nomad · error

must provide peer id or address

Error message

must provide peer id or address

What it means

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.

Source

Thrown at nomad/operator_endpoint.go:257

	// TransferLeadership is not supported until Raft protocol v3 or greater.
	if minRaftProtocol < 3 {
		op.logger.Warn("unsupported minimum common raft protocol version", "required", "3", "current", minRaftProtocol)
		reply.Err = errors.New("unsupported minimum common raft protocol version")
		return structs.NewErrRPCCoded(http.StatusBadRequest, reply.Err.Error())
	}

	var kind, testedVal string

	// The request must provide either an ID or an Address, this lets us validate
	// the request
	req.Validate()
	switch {
	case req.ID != "":
		kind, testedVal = "id", string(req.ID)
	case req.Address != "":
		kind, testedVal = "address", string(req.Address)
	default:
		reply.Err = errors.New("must provide peer id or address")
		return structs.NewErrRPCCoded(http.StatusBadRequest, reply.Err.Error())
	}

	// Get the raft configuration
	future := op.srv.raft.GetConfiguration()
	if err := future.Error(); err != nil {
		reply.Err = err
		return err
	}

	// Since this is an operation designed for humans to use, we will return
	// an error if the supplied ID or address isn't among the peers since it's
	// likely a mistake.
	var found bool
	for _, s := range future.Configuration().Servers {
		if s.ID == req.ID || s.Address == req.Address {
			reply.To = structs.NewRaftIDAddress(s.Address, s.ID)
			found = true

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Pass -peer-id <uuid> or -peer-address <ip:port> to the CLI command
  2. Include either "id" or "address" in the request body of the HTTP call
  3. Look up a valid peer id first via `nomad operator raft list-peers`

Example fix

// before
nomad operator raft transfer-leadership
// after
nomad operator raft transfer-leadership -peer-id 1b6088cd-1f6e-4d3e-9f7f-4b0f8e2a1234
Defensive patterns

Strategy: validation

Validate before calling

func validateTransferReq(req *structs.TransferLeaderRequest) error {
    if req.ID == "" && req.Address == "" {
        return errors.New("must supply -peer-id or -peer-address")
    }
    return nil
}

Type guard

func hasPeerTarget(id, address string) bool {
    return id != "" || address != ""
}

Try / catch

if err := transferLeadership(id, addr); err != nil {
    if strings.Contains(err.Error(), "must provide peer id or address") {
        return fmt.Errorf("supply peer target: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/229d6383eb22ecf3. Report an issue: GitHub.