hashicorp/nomad · error

error parsing server's last_log_term value: %s

Error message

error parsing server's last_log_term value: %s

What it means

Same endpoint as the last_log_index variant: RaftStats parses stats["last_log_term"] with strconv.ParseUint after successfully parsing the index. Failure means the raft library returned a last_log_term value that is empty or not a valid uint64, violating the expected raft stats contract.

Source

Thrown at nomad/status_endpoint.go:142

// RaftStats is used by Autopilot to query the raft stats of the local server.
func (s *Status) RaftStats(args *structs.GenericRequest, reply *structs.RaftStats) error {
	// note: we're intentionally throwing away any auth error here and only
	// authenticate so that we can measure rate metrics
	s.srv.Authenticate(s.ctx, args)
	s.srv.MeasureRPCRate("status", structs.RateMetricRead, args)

	stats := s.srv.raft.Stats()

	var err error
	reply.LastContact = stats["last_contact"]
	reply.LastIndex, err = strconv.ParseUint(stats["last_log_index"], 10, 64)
	if err != nil {
		return fmt.Errorf("error parsing server's last_log_index value: %s", err)
	}
	reply.LastTerm, err = strconv.ParseUint(stats["last_log_term"], 10, 64)
	if err != nil {
		return fmt.Errorf("error parsing server's last_log_term value: %s", err)
	}

	return nil
}

// HasNodeConn returns whether the server has a connection to the requested
// Node.
func (s *Status) HasNodeConn(args *structs.NodeSpecificRequest, reply *structs.NodeConnQueryResponse) error {
	// note: we're intentionally throwing away any auth error here and only
	// authenticate so that we can measure rate metrics
	s.srv.Authenticate(s.ctx, args)
	s.srv.MeasureRPCRate("status", structs.RateMetricRead, args)

	// Validate the args
	if args.NodeID == "" {
		return errors.New("Must provide the NodeID")
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Inspect the wrapped strconv message to confirm whether the value was empty vs malformed.
  2. Align Nomad client/server versions; ensure the server binary links the expected hashicorp/raft.
  3. Retry the call once the server has completed raft setup and elected a leader.
  4. Fall back to 'nomad operator raft list-peers' for leader/term information if the endpoint keeps failing.

Example fix

// before
term := reply.LastTerm // assume fine
// after (server-side defensive parse)
if lastTerm, ok := stats["last_log_term"]; ok && lastTerm != "" {
  reply.LastTerm, err = strconv.ParseUint(lastTerm, 10, 64)
} else {
  return fmt.Errorf("last_log_term missing from raft stats")
}
Defensive patterns

Strategy: retry

Type guard

func isRaftTermParseError(err error) bool { return err != nil && strings.Contains(err.Error(), "last_log_term") }

Try / catch

stats, err := srv.Status().RaftStats()
if isRaftTermParseError(err) {
  return fmt.Errorf("raft term unavailable: %w (use 'nomad operator raft list-peers')", err)
}

Prevention

When it happens

Trigger: Status().RaftStats RPC where strconv.ParseUint(stats["last_log_term"], 10, 64) fails — typically an empty string in the stats map from an uninitialized or incompatible raft instance.

Common situations: Nomad version mismatch between client expectations and server raft library; querying during very early server startup before raft has written any term; custom raft builds.

Related errors


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