hashicorp/nomad · error

Failed to parse X-Nomad-Index: %v

Error message

Failed to parse X-Nomad-Index: %v

What it means

In api/api.go:1187, parseQueryMeta reads blocking-query metadata from response headers; X-Nomad-Index must parse as a uint64. If the header is absent, empty, or non-numeric, the client returns this error. This indicates the response did not come from a genuine Nomad server endpoint (proxies, mocks, or non-Nomad services often omit it).

Source

Thrown at api/api.go:1187

	wm := &WriteMeta{RequestTime: rtt}
	parseWriteMeta(resp, wm)

	if out != nil {
		if err := decodeBody(resp, &out); err != nil {
			return nil, err
		}
	}
	return wm, nil
}

// parseQueryMeta is used to help parse query meta-data
func parseQueryMeta(resp *http.Response, q *QueryMeta) error {
	header := resp.Header

	// Parse the X-Nomad-Index
	index, err := strconv.ParseUint(header.Get("X-Nomad-Index"), 10, 64)
	if err != nil {
		return fmt.Errorf("Failed to parse X-Nomad-Index: %v", err)
	}
	q.LastIndex = index

	// Parse the X-Nomad-LastContact
	last, err := strconv.ParseUint(header.Get("X-Nomad-LastContact"), 10, 64)
	if err != nil {
		return fmt.Errorf("Failed to parse X-Nomad-LastContact: %v", err)
	}
	if last > math.MaxInt64 {
		return fmt.Errorf("Last contact duration is out of range: %d", last)
	}
	q.LastContact = time.Duration(last) * time.Millisecond
	q.NextToken = header.Get("X-Nomad-NextToken")

	// Parse the X-Nomad-KnownLeader
	switch header.Get("X-Nomad-KnownLeader") {
	case "true":
		q.KnownLeader = true

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify requests reach a real Nomad server: curl -si $NOMAD_ADDR/v1/nodes and check X-Nomad-Index is present
  2. Remove/fix proxies that strip X-Nomad-* headers, or re-add them via the proxy
  3. Check you are hitting /v1 API paths, not the web UI
  4. In tests, use the Nomad test server or add the header: w.Header().Set("X-Nomad-Index", "100")
  5. Confirm client and server versions are compatible

Example fix

// before: mock handler returns JSON without headers
w.Write([]byte(`{"Nodes":[]}`))
// after
w.Header().Set("X-Nomad-Index", "100")
w.Header().Set("X-Nomad-KnownLeader", "true")
w.Write([]byte(`{"Nodes":[]}`))
Defensive patterns

Strategy: validation

Validate before calling

resp, err := http.Get(cfg.Address + "/v1/nodes")
if err != nil { return err }
if resp.Header.Get("X-Nomad-Index") == "" {
	return errors.New("upstream is not a Nomad server (missing X-Nomad-Index)")
}

Type guard

func hasNomadMeta(h http.Header) bool {
	_, err := strconv.ParseUint(h.Get("X-Nomad-Index"), 10, 64)
	return err == nil
}

Try / catch

_, qm, err := client.Nodes().List(nil)
if err != nil && strings.Contains(err.Error(), "X-Nomad-Index") {
	return fmt.Errorf("responses lack Nomad metadata; check proxy header stripping / non-Nomad upstream: %w", err)
}

Prevention

When it happens

Trigger: Any blocking-query list/read call (Nodes().List, Jobs().Info, etc.) where the response lacks a valid X-Nomad-Index header — non-Nomad upstream, misconfigured proxy stripping headers, or test double returning plain responses.

Common situations: Pointing the client at a service mesh/gateway that strips X-Nomad-* headers; using a stub server in tests without the header; old/incompatible server versions; hitting the UI route instead of the API.

Understand the failure class

Related errors


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