hashicorp/nomad · error
Request body is empty
Error message
Request body is empty
What it means
decodeBody in command/agent/http.go decodes JSON HTTP request bodies for Nomad agent API endpoints. It rejects requests whose body is http.NoBody, i.e. an empty body, because the endpoint handlers require a JSON object to decode. Sending no body (or a body-less GET-style request) to a write endpoint that expects a payload triggers this error.
Source
Thrown at command/agent/http.go:912
}
// write response
if obj != nil {
resp.Write(obj)
}
}
return f
}
// isAPIClientError returns true if the passed http code represents a client error
func isAPIClientError(code int) bool {
return 400 <= code && code <= 499
}
// decodeBody is used to decode a JSON request body
func decodeBody(req *http.Request, out any) error {
if req.Body == http.NoBody {
return errors.New("Request body is empty")
}
dec := json.NewDecoder(req.Body)
return dec.Decode(&out)
}
// setIndex is used to set the index response header
func setIndex(resp http.ResponseWriter, index uint64) {
resp.Header().Set("X-Nomad-Index", strconv.FormatUint(index, 10))
}
// setKnownLeader is used to set the known leader header
func setKnownLeader(resp http.ResponseWriter, known bool) {
s := "true"
if !known {
s = "false"
}
resp.Header().Set("X-Nomad-KnownLeader", s)View on GitHub (pinned to 482b49bf1a)
Solutions
- Send a JSON body with the request, e.g. `curl -XPOST -d '{}' $NOMAD_ADDR/v1/acl/token/bootstrap`.
- Set Content-Type: application/json and pass the required fields for the endpoint (e.g. Name/Rules for policy upsert).
- Use a Nomad API client library that automatically serializes the request struct instead of hand-crafted empty POSTs.
- Check any intermediary proxy/gateway is not dropping the request body.
Example fix
// before
curl -XPOST $NOMAD_ADDR/v1/acl/policy/my-policy
// after
curl -XPOST -H 'Content-Type: application/json' -d '{"Name":"my-policy","Rules":"..."}' $NOMAD_ADDR/v1/acl/policy/my-policy Defensive patterns
Strategy: validation
Validate before calling
// client-side check before POSTing
body, _ := json.Marshal(payload)
if len(body) == 0 {
return errors.New("refusing to POST: request body is empty")
} Try / catch
resp, err := http.Post(url, "application/json", bytes.NewReader(body))
if err != nil {
return err
}
if strings.Contains(readErrHint(resp), "Request body is empty") {
return fmt.Errorf("endpoint %s requires a JSON body; got none", url)
} Prevention
- Always send a JSON body (even `{}`) to Nomad write endpoints.
- Use the official Nomad API client instead of hand-built POSTs.
- Set Content-Type: application/json on all mutating requests.
- Verify proxies/gateways preserve request bodies.
When it happens
Trigger: POSTing to ACL endpoints (aclPolicyUpdate, ACLTokenBootstrap, aclTokenUpdate, aclRoleUpsertRequest, aclAuthMethodUpsertRequest) or ExchangeOneTimeToken with an empty request body — e.g. `curl -XPOST /v1/acl/token/bootstrap` with no -d data on a client where the content body is stripped.
Common situations: curl POST without -d/--data; HTTP clients that omit a body for POST; a reverse proxy stripping request bodies; calling a write endpoint with the wrong HTTP method tooling that sends no payload.
Related errors
- failed to marshal command into json: %v
- multiple lock operations
- unexpected ExpirationLeeway type: %v
- unexpected NotBeforeLeeway type: %v
- unexpected ClockSkewLeeway type: %v
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/8c95e0b54977ace1.
Report an issue: GitHub.